aboutsummaryrefslogtreecommitdiff
path: root/files/.vim/autoload/java_parser.vim
diff options
context:
space:
mode:
Diffstat (limited to 'files/.vim/autoload/java_parser.vim')
-rw-r--r--files/.vim/autoload/java_parser.vim3500
1 files changed, 0 insertions, 3500 deletions
diff --git a/files/.vim/autoload/java_parser.vim b/files/.vim/autoload/java_parser.vim
deleted file mode 100644
index 5e1ec38..0000000
--- a/files/.vim/autoload/java_parser.vim
+++ /dev/null
@@ -1,3500 +0,0 @@
-" Vim autoload script for a JAVA PARSER and more.
-" Language: Java
-" Maintainer: cheng fang <fangread@yahoo.com.cn>
-" Last Changed: 2007-09-16
-" Version: 0.67
-" Copyright: Copyright (C) 2007 cheng fang. All rights reserved.
-" License: Vim License (see vim's :help license)
-
-
-if exists("g:loaded_javaparser") || version < 700 || &cp
- finish
-endif
-let g:loaded_javaparser = 'v0.67'
-
-
-" Constants used by scanner and parser {{{1
-let s:EOI = ''
-
-let s:keywords = {'+': 'PLUS', '-': 'SUB', '!': 'BANG', '%': 'PERCENT', '^': 'CARET', '&': 'AMP', '*': 'STAR', '|': 'BAR', '~': 'TILDE', '/': 'SLASH', '>': 'GT', '<': 'LT', '?': 'QUES', ':': 'COLON', '=': 'EQ', '++': 'PLUSPLUS', '--': 'SUBSUB', '==': 'EQEQ', '<=': 'LTEQ', '>=': 'GTEQ', '!=': 'BANGEQ', '<<': 'LTLT', '>>': 'GTGT', '>>>': 'GTGTGT', '+=': 'PLUSEQ', '-=': 'SUBEQ', '*=': 'STAREQ', '/=': 'SLASHEQ', '&=': 'AMPEQ', '|=': 'BAREQ', '^=': 'CARETEQ', '%=': 'PERCENTEQ', '<<=': 'LTLTEQ', '>>=': 'GTGTEQ', '>>>=': 'GTGTGTEQ', '||': 'BARBAR', '&&': 'AMPAMP', 'abstract': 'ABSTRACT', 'assert': 'ASSERT', 'boolean': 'BOOLEAN', 'break': 'BREAK', 'byte': 'BYTE', 'case': 'CASE', 'catch': 'CATCH', 'char': 'CHAR', 'class': 'CLASS', 'const': 'CONST', 'continue': 'CONTINUE', 'default': 'DEFAULT', 'do': 'DO', 'double': 'DOUBLE', 'else': 'ELSE', 'extends': 'EXTENDS', 'final': 'FINAL', 'finally': 'FINALLY', 'float': 'FLOAT', 'for': 'FOR', 'goto': 'GOTO', 'if': 'IF', 'implements': 'IMPLEMENTS', 'import': 'IMPORT', 'instanceof': 'INSTANCEOF', 'int': 'INT', 'interface': 'INTERFACE', 'long': 'LONG', 'native': 'NATIVE', 'new': 'NEW', 'package': 'PACKAGE', 'private': 'PRIVATE', 'protected': 'PROTECTED', 'public': 'PUBLIC', 'return': 'RETURN', 'short': 'SHORT', 'static': 'STATIC', 'strictfp': 'STRICTFP', 'super': 'SUPER', 'switch': 'SWITCH', 'synchronized': 'SYNCHRONIZED', 'this': 'THIS', 'throw': 'THROW', 'throws': 'THROWS', 'transient': 'TRANSIENT', 'try': 'TRY', 'void': 'VOID', 'volatile': 'VOLATILE', 'while': 'WHILE', 'true': 'TRUE', 'false': 'FALSE', 'null': 'NULL', '(': 'LPAREN', ')': 'RPAREN', '{': 'LBRACE', '}': 'RBRACE', '[': 'LBRACKET', ']': 'RBRACKET', ';': 'SEMI', ',': 'COMMA', '.': 'DOT', 'enum': 'ENUM', '...': 'ELLIPSIS', '@': 'MONKEYS_AT'}
-
-let s:Flags = {'PUBLIC': 0x1, 'PRIVATE': 0x2, 'PROTECTED': 0x4, 'STATIC': 0x8, 'FINAL': 0x10, 'SYNCHRONIZED': 0x20, 'VOLATILE': 0x40, 'TRANSIENT': 0x80, 'NATIVE': 0x100, 'INTERFACE': 0x200, 'ABSTRACT': 0x400, 'STRICTFP': 0x800, 'SYNTHETIC': 0x1000, 'ANNOTATION': 0x2000, 'ENUM': 0x4000, 'StandardFlags':0x0fff, 'ACC_SUPER': 0x20, 'ACC_BRIDGE': 0x40, 'ACC_VARARGS': 0x80, 'DEPRECATED': 0x20000, 'HASINIT': 0x40000, 'BLOCK': 0x100000, 'IPROXY': 0x200000, 'NOOUTERTHIS': 0x400000, 'EXISTS': 0x800000, 'COMPOUND': 0x1000000, 'CLASS_SEEN': 0x2000000, 'SOURCE_SEEN': 0x4000000, 'LOCKED': 0x8000000, 'UNATTRIBUTED': 0x10000000, 'ANONCONSTR': 0x20000000, 'ACYCLIC': 0x40000000, 'BRIDGE': 1.repeat('0', 31), 'PARAMETER': 1.repeat('0', 33), 'VARARGS': 1.repeat('0', 34), 'ACYCLIC_ANN': 1.repeat('0', 35), 'GENERATEDCONSTR': 1.repeat('0', 36), 'HYPOTHETICAL': 1.repeat('0', 37), 'PROPRIETARY': 1.repeat('0', 38)}
-
-let s:RE_ANYTHING_AND_NEWLINE = '\(\(.\|\n\)*\)'
-let s:RE_LINE_COMMENT = '//.*$'
-let s:RE_COMMENT_SP = '/\*\*/'
-let s:RE_COMMENT = ''
-let s:RE_BRACKETS = '\(\s*\[\s*\]\)'
-
-let s:RE_IDENTIFIER = '[a-zA-Z_$][a-zA-Z0-9_$]*'
-let s:RE_QUALID = s:RE_IDENTIFIER. '\(\s*\.\s*' .s:RE_IDENTIFIER. '\)*'
-let s:RE_TYPE_NAME = s:RE_QUALID
-let s:RE_REFERENCE_TYPE = s:RE_QUALID . s:RE_BRACKETS . '*' " TypeName || Type[]
-let s:RE_TYPE = s:RE_REFERENCE_TYPE " PrimitiveType || ReferenceType
-let s:RE_TYPE_VARIABLE = s:RE_IDENTIFIER
-let s:RE_VAR_DECL_ID = s:RE_IDENTIFIER . s:RE_BRACKETS . '*'
-
-let s:RE_TYPE_PARAMS = ''
-
-let s:RE_THROWS = 'throws\s\+' . s:RE_TYPE_NAME . '\(\s*,\s*' . s:RE_TYPE_NAME . '\)*'
-let s:RE_FORMAL_PARAM = '\(final\s*\)\='. s:RE_TYPE . '\s\+' . s:RE_VAR_DECL_ID
-let s:RE_FORMAL_PARAM_LIST = s:RE_FORMAL_PARAM . '\(\s*,\s*' . s:RE_FORMAL_PARAM . '\)*'
-let s:RE_FORMAL_PARAM2 = '^\s*\(final\s*\)\=\('. s:RE_TYPE . '\)\s\+\(' . s:RE_IDENTIFIER . '\)' . s:RE_BRACKETS . '*'
-
-let s:RE_MEMBER_MODS = '\%(PUBLIC\|PROTECTED\|PRIVATE\|ABSTRACT\|STATIC\|FINAL\|TRANSIENT\|VOLATILE\|SYNCHRONIZED\|NATIVE\|STRICTFP\)'
-let s:RE_MEMBER_HEADER = '\s*\(\%(' .s:RE_MEMBER_MODS. '\s\+\)\+\)\(' .s:RE_IDENTIFIER. '\%(\s*\.\s*' .s:RE_IDENTIFIER. '\)*\%(\s*\[\s*\]\)*\)\s\+\(' .s:RE_IDENTIFIER. '\)'
-
-" API {{{1
-
-let s:PROTOTYPE = {'s:options': {}, 'b:buf': '', 'b:buflen': 0, 'b:lines': [], 'b:idxes': [0], 'b:bp': -1, 'b:ch': '', 'b:line': 0, 'b:col': 0, 'b:pos': 0, 'b:endPos': 0, 'b:prevEndPos': 0, 'b:errPos': -1, 'b:errorEndPos': -1, 'b:sbuf': '', 'b:name': '', 'b:token': '', 'b:docComment': '', 'b:radix': 0, 'b:unicodeConversionBp': -1, 'b:scanStrategy': 0, 'b:allowGenerics': 1, 'b:allowVarargs': 1, 'b:allowAsserts': 1, 'b:allowEnums': 1, 'b:allowForeach': 1, 'b:allowStaticImport': 1, 'b:allowAnnotations': 1, 'b:keepDocComments': 1, 'b:mode': 0, 'b:lastmode': 0, 'b:log': [], 'b:et_perf': '', 'b:et_nextToken_count': 0}
-
-" Function to initialize the parser
-" parameters:
-" - lines List of code text
-" - options A set of options
-fu! java_parser#InitParser(lines, ...)
- let s:options = a:0 == 0 ? {} : a:1
-
- " internal variables for scanning
-" let b:buf = '' " The input buffer
- let b:buflen = 0 " index of one past last character in buffer. also eofPos
- let b:lines = a:lines " The input buffer
- let b:idxes = [0] " Begin index of every lines
- let b:bp = -1 " index of next character to be read.
- let b:ch = '' " The current character.
- let b:line = 0 " The line number position of the current character.
- let b:col = 0 " The column number position of the current character.
- let b:pos = 0 " The token's position, 0-based offset from beginning of text.
- let b:endPos = 0 " Character position just after the last character of the token.
- let b:prevEndPos = 0 " The last character position of the previous token.
- let b:errPos = -1 " The position where a lexical error occurred
- let b:errorEndPos = -1 "
- let b:sbuf = '' " A character buffer for literals.
- let b:name = '' " The name of an identifier or token:
- let b:token = 0 " The token, set by s:nextToken().
- let b:docComment = ''
- let b:radix = 0 " The radix of a numeric literal token.
- let b:unicodeConversionBp =-1 " The buffer index of the last converted unicode character
-
- let b:scanStrategy = get(s:options, 'scanStrategy', -1) " 0 - only class members when parse full file;
- " 1 - keep statement as a whole string;
- " 2 - all
- " -1 - enable quick recognition of declarations in common form.
-
- " language feature options.
- let b:allowGenerics = get(s:options, 'allowGenerics', 1)
- let b:allowVarargs = get(s:options, 'allowVarargs', 1)
- let b:allowAsserts = get(s:options, 'allowAsserts', 1)
- let b:allowEnums = get(s:options, 'allowEnums', 1)
- let b:allowForeach = get(s:options, 'allowForeach', 1)
- let b:allowStaticImport = get(s:options, 'allowStaticImport', 1)
- let b:allowAnnotations = get(s:options, 'allowAnnotations', 1)
- let b:keepDocComments = get(s:options, 'keepDocComments', 1)
-
- let b:mode = 0 " The current mode.
- let b:lastmode = 0 " The mode of the term that was parsed last.
-
-
- let b:log = []
-
- let b:et_perf = ''
- let b:et_nextToken_count = 0
-
-" let b:buf = join(a:lines, "\r")
-" let b:buflen = strlen(b:buf)
- for line in a:lines
- let b:buflen += strlen(line) + 1
- call add(b:idxes, b:buflen)
- endfor
- call add(b:lines, s:EOI) " avoid 'list index out of range' error from lines[] in java_scanChar
- " if b:bp >= b:buflen
- " return s:EOI
- " endif
-
- " initialize scanner
- call s:scanChar() " be ready for scanning
- call s:nextToken() " prime the pump
-endfu
-
-fu! java_parser#FreeParser()
- for varname in keys(s:PROTOTYPE)
- exe "if exists(" . string(varname) . ") | unlet " . varname . " | endif"
- endfor
-endfu
-
-fu! java_parser#GetSnapshot()
- let snapshot = {}
- for varname in keys(s:PROTOTYPE)
- exe "let snapshot[" . string(varname) . "] = " . varname
- endfor
- return snapshot
-endfu
-
-fu! java_parser#Restore(snapshot)
- for key in keys(a:snapshot)
- exe "let " . key . "=" . string(a:snapshot[key])
- endfor
-endfu
-
-" move b:bp and b:pos to the specified position
-fu! java_parser#GotoPosition(pos)
- let b:bp = a:pos-1
- let b:pos = a:pos
- let p = java_parser#DecodePos(b:bp)
- let b:line = p.line
- let b:col = p.col
- call s:scanChar()
- call s:nextToken()
-endfu
-
-fu! java_parser#compilationUnit()
- return s:compilationUnit()
-endfu
-
-fu! java_parser#block()
- return s:block()
-endfu
-
-fu! java_parser#statement()
- return s:blockStatements()
-endfu
-
-fu! java_parser#expression()
- return s:expression()
-endfu
-
-fu! java_parser#nextToken()
- return s:nextToken()
-endfu
-
-
-" Tree {{{1
-let s:TTree = {'tag': '', 'pos': 0} " Root class for AST nodes.
-
-" Tree maker functions {{{2
-fu! s:ClassDef(pos, mods, ...)
- return {'tag': 'CLASSDEF', 'pos': a:pos, 'mods': a:mods, 'name': ''}
-endfu
-
-fu! s:VarDef(pos, mods, name, vartype)
- return {'tag': 'VARDEF', 'pos': a:pos, 'mods': a:mods, 'name': a:name, 'vartype': a:vartype}
-endfu
-
-fu! s:Unary(pos, opcode, arg)
- return {'tag': a:opcode, 'pos': a:pos, 'arg': a:arg}
-endfu
-
-fu! s:Binary(pos, opcode, lhs, rhs, ...)
- return {'tag': a:opcode, 'pos': a:pos, 'lhs': a:lhs, 'rhs': a:rhs}
-endfu
-
-fu! s:TypeCast(pos, clazz, expr)
- return {'tag': 'TYPECAST', 'pos': a:pos, 'clazz': a:clazz, 'expr': a:expr}
-endfu
-
-fu! s:Select(pos, selected, name)
- return {'tag': 'SELECT', 'pos': a:pos, 'selected': a:selected, 'name': a:name}
-endfu
-
-fu! s:Ident(pos, name)
- return {'tag': 'IDENT', 'pos': a:pos, 'name': a:name}
-endfu
-
-fu! s:TypeArray(pos, elementtype)
- return {'tag': 'TYPEARRAY', 'pos': a:pos, 'elementtype': a:elementtype}
-endfu
-
-fu! s:Modifiers(pos, flags, annotations)
- let noFlags = s:BitAnd(a:flags, s:Flags.StandardFlags) == 0
- let mods = {'tag': 'MODIFIERS', 'flags': a:flags}
- let mods.pos = noFlags && empty(a:annotations) ? -1 : a:pos
- if !empty(a:annotations)
- let mods.annotations = a:annotations
- endif
- return mods
-endfu
-
-
-" {{{2
-fu! java_parser#IsStatement(tree)
- return has_key(a:tree, 'tag') && a:tree.tag =~# '^\(CLASSDEF\|VARDEF\|BLOCK\|IF\|DOLOOP\|WHILELOOP\|FORLOOP\|FOREACHLOOP\|SWITCH\|TRY\|EXEC\|LABELLED\|SYNCHRONIZED\|CASE\|BREAK\|RETURN\|SKIP\|THROW\|ASSERT\|CONTINUE\)$'
-endfu
-
-" Tree Helper {{{1
-fu! java_parser#type2Str(type)
- if type(a:type) == type("")
- return a:type
- endif
-
- let t = a:type
- if t.tag == 'IDENTIFIER'
- return t.value
- elseif t.tag == 'IDENT'
- return t.name
- elseif t.tag == 'TYPEIDENT'
- return t.typetag
- elseif t.tag == 'SELECT'
- return java_parser#type2Str(t.selected) . '.' . t.name
- elseif t.tag == 'TYPEARRAY'
- return java_parser#type2Str(t.elementtype) . '[]'
- elseif t.tag == 'TYPEAPPLY'
- return t.clazz.name
- elseif t.tag == 'TEMPLATE'
- let s = t.clazz.value . '<'
- for arg in t.arguments
- let s .= arg.value
- endfor
- let s .= '>'
- return s
- endif
-endfu
-
-fu! s:vardef2Str(vardef)
- return java_parser#type2Str(a:vardef.vartype) . ' ' . a:vardef.name
-endfu
-
-fu! s:method2Str(methoddef)
- let m = a:methoddef
- let desc = m.r . ' ' . m.n . '('
- for item in m.params
- let desc .= s:vardef2Str(item) . ','
- endfor
- let desc = substitute(desc, ',$', '', '')
- let desc .= ')'
- return desc
-endfu
-
-" Scanner {{{1
-
-" nextToken() {{{2
-fu! s:nextToken()
- let b:prevEndPos = b:endPos
- let b:et_nextToken_count += 1
- let b:sbuf = ''
- while 1
- let b:pos = b:bp
- if b:ch =~ '[ \t\r\n ]' " - FF
- " OAO optimized code: skip spaces
- let b:col = match(b:lines[b:line], '[^ \t\r\n ]\|$', b:col)
- let b:bp = b:idxes[b:line] + b:col
- call s:scanChar()
- let b:endPos = b:bp
- continue
-
- elseif b:ch =~ '[a-zA-Z$_]'
- " read a identifier
- call s:scanIdent()
- return
-
- elseif b:ch == '0'
- call s:scanChar()
- " hex
- if b:ch == 'x' || b:ch == 'X'
- call s:scanChar()
- if b:ch == '.'
- call s:scanHexFractionAndSuffix(0)
- elseif s:isDigit(16)
- call s:scanNumber(16)
- else
- call s:LexError("invalid.hex.number")
- endif
- " oct
- else
- let b:sbuf .= '0'
- call s:scanNumber(8)
- endif
- return
-
- elseif b:ch =~ '[1-9]'
- " read number
- call s:scanNumber(10)
- return
-
- elseif b:ch == '.'
- call s:scanChar()
- if b:ch =~ '[0-9]'
- let b:sbuf .= '.'
- call s:scanFractionAndSuffix()
- " JAVA5 ELLIPSIS
- elseif b:ch == '.'
- let b:sbuf .= '..'
- call s:scanChar()
- if b:ch == '.'
- call s:scanChar()
- let b:sbuf .= '.'
- let b:token = 'ELLIPSIS'
- else
- call s:LexError('malformed.fp.lit')
- endif
- else
- let b:token = 'DOT'
- endif
- return
-
- elseif b:ch =~ '[,;(){}[\]]'
- let b:token = s:keywords[b:ch]
- call s:scanChar()
- return
-
- elseif b:ch == '/'
- let status = s:scanComment()
- if status == 1
- continue
- elseif status == 2
- return
- elseif b:ch == '='
- let b:name = '/='
- let b:token = 'SLASHEQ'
- call s:scanChar()
- else
- let b:name = '/'
- let b:token = 'SLASH'
- endif
- return
-
-
- elseif b:ch == "'"
- call s:scanSingleQuote()
- return
-
- elseif b:ch == '"'
- call s:scanDoubleQuote()
- return
-
- else
- if s:IsSpecial(b:ch)
- call s:scanOperator()
- elseif b:ch =~ '[a-zA-Z_]'
- call s:scanIdent()
- elseif b:bp >= b:buflen
- let b:token = 'EOF'
- else
- call s:LexError("illegal.char '" . b:ch . "'")
- call s:scanChar()
- endif
- return
- endif
- endwhile
-endfu
-
-" scanChar() Read next character. {{{2
-" one buf version
-"fu! s:scanChar()
-" let b:bp += 1
-" if b:bp % 256 == 0
-" let b:buf2 = strpart(b:buf, b:bp, 256)
-" endif
-" let b:ch = b:buf2[b:bp % 256]
-"" let b:ch = b:buf[b:bp] " it will be extremely slow when buf is large
-" "call s:Trace( "'" . b:ch . "'" )
-"
-" if b:ch == "\r"
-" let b:line += 1
-" let b:col = 0
-" elseif b:ch == "\n"
-" if b:bp == 0 || b:buf[b:bp-1] == "\r"
-" let b:line += 1
-" let b:col = 0
-" endif
-" else
-" let b:col += 1
-" endif
-"endfu
-
-" Read next character. multiple lines version
-fu! s:scanChar()
- let b:bp+=1
- let b:ch=b:lines[b:line][b:col]
- let b:col+=1
- if b:ch==''
- let b:ch="\r"
- let b:line+=1
- let b:col=0
- endif
-
- if b:ch == '\'
- call s:convertUnicode()
- endif
-endfu
-
-fu! java_parser#CharAt(line, col)
- let ch=b:lines[a:line][a:col]
- if ch == ''
- let ch = "\r"
- endif
- return ch
-endfu
-
-fu! s:convertUnicode()
- if b:ch == '\' && b:unicodeConversionBp != b:bp
- "if java_parser#CharAt(b:bp+1) == 'u'
- "call s:scanChar()
- "endif
- endif
-endfu
-
-" putChar() is substituted with
-" let b:sbuf .= '.'
-
-" scanIdent() {{{2
-" OAO optimized code
-fu! s:scanIdent()
- let col_old = b:col
- let b:col = match(b:lines[b:line], '[^a-zA-Z0-9$_]\|$', b:col)
- let b:name = strpart(b:lines[b:line], col_old-1, b:col-col_old+1)
- let b:token = get(s:keywords, b:name, 'IDENTIFIER')
- call s:Debug('name: "' . b:name . '" of token type ' . b:token )
- let b:bp = b:idxes[b:line] + b:col
- call s:scanChar()
-endfu
-
-" Standard implementation
-fu! s:scanIdent_old()
- " do ... while ()
- let b:sbuf .= b:ch
- call s:scanChar()
- if b:ch !~ '[a-zA-Z0-9$_]' || b:bp >= b:buflen
- let b:name = b:sbuf
- let b:token = has_key(s:keywords, b:name) ? s:keywords[b:name] : 'IDENTIFIER'
- call s:Debug('name: "' . b:name . '" of token type ' . b:token )
- return
- endif
-
- while (1)
- let b:sbuf .= b:ch
- call s:scanChar()
- if b:ch !~ '[a-zA-Z0-9$_]' || b:bp >= b:buflen
- let b:name = b:sbuf
- let b:token = has_key(s:keywords, b:name) ? s:keywords[b:name] : 'IDENTIFIER'
- call s:Debug('name: "' . b:name . '" of token type ' . b:token )
- break
- endif
- endwhile
-endfu
-
-" digit() {{{2
-" Convert an ASCII digit from its base (8, 10, or 16) to its value.
-" NOTE: This only implement isdigit() check
-fu! s:digit(base)
- let c = b:ch
- "let result =
-endfu
-
-fu! s:isDigit(base)
- if a:base == 8
- return b:ch =~ '[0-7]'
- elseif a:base == 16
- return b:ch =~ '[0-9a-fA-F]'
- elseif a:base == 10
- return b:ch =~ '[0-9]'
- endif
-endfu
-
-" scanNumber() {{{2
-fu! s:scanNumber(radix)
- let b:radix = a:radix
- let digitRadix = a:radix <= 10 ? 10 : 16
- let seendigit = 0
- while s:isDigit(a:radix)
- let seendigit = 1
- let b:sbuf .= b:ch
- call s:scanChar()
- endwhile
- if a:radix == 16 && b:ch == '.'
- call s:scanHexFractionAndSuffix(seendigit)
- elseif seendigit && a:radix == 16 && (b:ch == 'p' || b:ch == 'P')
- call s:scanHexExponentAndSuffix()
- elseif a:radix <= 10 && b:ch == '.'
- let b:sbuf .= b:ch
- call s:scanChar()
- call s:scanFractionAndSuffix()
- elseif a:radix <= 10 && b:ch =~ '[eEfFdD]'
- call s:scanFractionAndSuffix()
- else
- if b:ch == 'l' || b:ch == 'L'
- call s:scanChar()
- let b:token = 'LONGLITERAL'
- else
- let b:token = 'INTLITERAL'
- endif
- endif
-endfu
-
-fu! s:scanHexExponentAndSuffix()
- if b:ch == 'p' || b:ch == 'P'
- let b:sbuf .= b:ch
- call s:scanChar()
- if b:ch == '+' || b:ch == '-'
- let b:sbuf .= b:ch
- call s:scanChar()
- endif
-
- if '0' <= b:ch && b:ch <= '9'
- let b:sbuf .= b:ch
- call s:scanChar()
- while '0' <= b:ch && b:ch <= '9'
- let b:sbuf .= b:ch
- call s:scanChar()
- endwhile
-
- "if !b:allowHexFloats
- "elseif !b:hexFloatsWork
- " call s:LexError("unsupported.cross.fp.lit")
- "endif
- else
- call s:LexError("malformed.fp.lit")
- endif
- else
- call s:LexError("malformed.fp.lit")
- endif
-
- if b:ch == 'f' || b:ch == 'F'
- let b:sbuf .= b:ch
- call s:scanChar()
- let b:token = 'FLOATLITERAL'
- else
- if b:ch == 'f' || b:ch == 'F'
- let b:sbuf .= b:ch
- call s:scanChar()
- endif
- let b:token = 'DOUBLELITERAL'
- endif
-endfu
-
-fu! s:scanFraction()
- " scan fraction
- while b:ch =~ '[0-9]'
- let b:sbuf .= b:ch
- call s:scanChar()
- endwhile
-
- " floating point number
- if b:ch == 'e' || b:ch == 'E'
- let b:sbuf .= b:ch
- call s:scanChar()
-
- if b:ch == '+' || b:ch == '-'
- let b:sbuf .= b:ch
- call s:scanChar()
- endif
-
- if b:ch =~ '[0-9]'
- let b:sbuf .= b:ch
- call s:scanChar()
- while b:ch =~ '[0-9]'
- let b:sbuf .= b:ch
- call s:scanChar()
- endwhile
- return
- endif
-
- call s:LexError("malformed.fp.lit")
- endif
-endfu
-
-" Read fractional part and 'd' or 'f' suffix of floating point number.
-fu! s:scanFractionAndSuffix()
- call s:scanFraction()
- if b:ch == 'f' || b:ch == 'F'
- let b:sbuf .= b:ch
- call s:scanChar()
- let b:token = 'FLOATLITERAL'
- else
- if b:ch == 'd' || b:ch == 'D'
- let b:sbuf .= b:ch
- call s:scanChar()
- endif
- let b:token = 'DOUBLELITERAL'
- endif
-endfu
-
-fu! s:scanHexFractionAndSuffix(seendigit)
- let seendigit = a:seendigit
- let b:radix = 16
- if b:ch != '.' | echoerr "b:ch != '.'" | endif
-
- let b:sbuf .= b:ch
- call s:scanChar()
- while s:isDigit(16)
- let seendigit = 1
- let b:sbuf .= b:ch
- call s:scanChar()
- endwhile
-
- if !seendigit
- call s:LexError("invalid.hex.number")
- else
- call s:scanHexExponentAndSuffix()
- endif
-endfu
-
-" scanLitChar() {{{2
-fu! s:scanLitChar()
- if b:ch == '\'
- call s:scanChar()
- if b:ch =~ '[0-7]'
- let leadch = b:ch
- let oct = b:ch
- call s:scanChar()
- if b:ch =~ '[0-7]'
- let oct = oct * 8 + b:ch
- call s:scanChar()
- if leadch <= '3' && '0' <= b:ch && b:ch <= '7'
- let oct = oct * 8 + b:ch
- call s:scanChar()
- endif
- endif
- let b:sbuf .= oct
-
- elseif b:ch == "'" || b:ch =~ '[btnfr"\\]'
- let b:sbuf .= b:ch
- call s:scanChar()
-
- " unicode escape
- elseif b:ch == 'u'
- while b:ch =~ '[a-zA-Z0-9]'
- call s:scanChar()
- endwhile
-
- else
- call s:LexError("illegal.esc.char")
- endif
-
- elseif b:bp < b:buflen
- let b:sbuf .= b:ch
- call s:scanChar()
- endif
-endfu
-
-" scanOperator() {{{2
-fu! s:scanOperator()
- while 1
- if !has_key(s:keywords, b:sbuf . b:ch)
- break
- endif
-
- let b:sbuf .= b:ch
- let b:token = get(s:keywords, b:sbuf, 'IDENTIFIER')
- call s:Debug('sbuf: "' . b:sbuf . '" of token type ' . b:token )
- call s:scanChar()
- if !s:IsSpecial(b:ch)
- break
- endif
- endwhile
-endfu
-
-" NOTE: add @ for JAVA5
-fu! s:IsSpecial(ch)
- return a:ch =~ '[!%&*?+-:<=>^|~@]'
-endfu
-
-" scan comment {{{2
-" return 0 - not comment, 1 - succeeded to scan comment, 2 - unclosed comment
-fu! s:scanComment()
- call s:scanChar()
- " line comment
- if b:ch == '/'
- let b:token = 'LINECOMMENT'
- call s:Info('line comment')
- call s:SkipLineComment()
- let b:endPos = b:bp
- return 1
-
- " classic comment
- " test cases: /**/, /***/, /*******/, /*** astatement; /***/, /*/
- elseif b:ch == '*'
- let b:token = 'BLOCKCOMMENT'
- call s:Info('block comment')
- call s:scanChar()
- let time = reltime()
- " javadoc
- if b:ch == '*'
- let b:docComment = s:scanDocComment()
- " normal comment
- else
- call s:skipComment()
- endif
- let b:et_perf .= "\r" . 'comment ' . reltimestr(reltime(time))
-
- if b:ch == '/'
- call s:Info('end block comment')
- call s:scanChar()
- let b:endPos = b:bp
- return 1
- else
- call s:LexError('unclosed.comment')
- return 2
- endif
- endif
- return 0
-endfu
-
-fu! s:SkipLineComment()
- " OAO optimized code
- let b:ch = "\r"
- let b:line += 1
- let b:col = 0
- let b:bp = b:idxes[b:line] + b:col
-
- " OLD
- "call s:scanChar()
- "while (b:ch != "\r")
- " call s:scanChar()
- "endwhile
-endfu
-
-fu! s:skipComment()
- if b:ch == '*'
- call s:scanChar()
- if b:ch == '/'
- return
- else " NOTE: go back
- let b:ch = '*'
- let b:bp -= 1
- let b:col -= 1
- endif
- endif
-
- " OAO optimized code
- if s:Stridx('*/') > -1
- call s:scanChar()
- endif
-
-" " Standard implementation
-" while b:bp < b:buflen
-" if b:ch == '*'
-" call s:scanChar()
-" if b:ch == '/'
-" break
-" endif
-" else
-" call s:scanChar()
-" endif
-" endwhile
-endfu
-
-fu! s:scanDocComment()
- call s:Info('It is javadoc')
- return s:skipComment()
-
- " skip star '*'
- while (b:bp < b:buflen && b:ch == '*')
- call s:scanChar()
- endwhile
-
- if b:bp < b:buflen && b:ch == '/'
- return ''
- endif
-
- let result = ''
- while b:bp < b:buflen
- if b:ch == '*'
- call s:scanChar()
- if b:ch == '/'
- break
- else
- let result .= b:ch
- endif
- else
- call s:scanChar()
- let result .= b:ch
- endif
- endwhile
-
- return result
-endfu
-
-" scan single quote {{{2
-fu! s:scanSingleQuote()
- call s:scanChar()
- if (b:ch == "'")
- call s:LexError("empty.char.lit")
- else
- if (b:ch =~ '[\r\n]')
- call s:LexError("illegal.line.end.in.char.lit")
- endif
-
- call s:scanLitChar()
- if b:ch == "'"
- call s:scanChar()
- let b:token = 'CHARLITERAL'
- else
- call s:LexError("unclosed.char.lit")
- endif
- endif
-endfu
-
-" scan double quote {{{2
-" test cases:
-" 'a"";'
-" 'a"b,c";'
-" 'a"b,\"c";'
-" 'a"b,\\"c";'
-" 'a"b,\\\"c";'
-" 'a"b,\\\\"c";'
-" 'a"b,\\\"c;' " NOTE: cannot handle
-fu! s:scanDoubleQuote()
- if match(b:lines[b:line], '\\"', b:col) == -1
- let idx = matchend(b:lines[b:line], '\(\\\(["\\''ntbrf]\)\|[^"]\)*"', b:col)
- if idx != -1
- let b:sbuf = strpart(b:lines[b:line], b:col, idx-b:col-1)
- let b:col = idx-1 " back to the end
- let b:bp = b:idxes[b:line] + b:col
- call s:scanChar()
- let b:token = 'STRINGLITERAL'
- else
- call s:LexError("unclosed.str.lit")
- endif
- call s:scanChar()
- return
- endif
-
-
- call s:scanChar()
- while b:ch !~ '["\r\n]' && b:bp < b:buflen
- call s:scanLitChar()
- endwhile
-
- if b:ch == '"'
- let b:token = 'STRINGLITERAL'
- call s:scanChar()
- else
- call s:LexError("unclosed.str.lit")
- endif
-endfu
-
-" lex errors {{{2
-fu! s:LexError(key, ...)
- let pos = a:0 == 0 ? b:pos : a:1
- let b:token = 'ERROR'
- let b:errPos = pos
- call s:Log(4, b:pos, '[lex error]:' . s:Pos2Str(pos) . ': ' . a:key)
-endfu
-
-" Scanner Helper {{{1
-" gotoMatchEnd {{{2
-fu! s:gotoMatchEnd(one, another, ...)
- while b:bp < b:buflen
- if b:ch == a:another
- call s:scanChar()
- if has_key(s:keywords, a:another)
- let b:token = s:keywords[a:another]
- else
- echoerr '<strange>'
- endif
- break
-
- elseif b:ch == a:one
- call s:scanChar()
- call s:gotoMatchEnd(a:one, a:another)
-
- " skip commment
- elseif b:ch == '/'
- call s:scanComment()
-
- " skip literal character
- elseif b:ch == "'"
- call s:scanSingleQuote()
-
- " skip literal string
- elseif b:ch == '"'
- call s:scanDoubleQuote()
-
- else
- " OAO
- call s:Match('[' . a:one . a:another . '/"'']')
- " OLD
- "call s:scanChar()
- endif
- endwhile
-
- " For such situation: after accept one token, the next token is just the same.
- let nextTokenIsLBRACE = a:0 == 0 ? 0 : a:1
- if nextTokenIsLBRACE
- call s:gotoMatchEnd(a:one, a:another)
- endif
-
- return b:bp
-endfu
-
-" gotoSemi {{{2
-fu! s:gotoSemi()
- while b:bp < b:buflen
- if b:ch == ';'
- let b:pos = b:bp
- call s:scanChar()
- let b:token = 'SEMI'
- return
-
- " skip commment
- elseif b:ch == '/'
- call s:scanComment()
-
- " skip literal character
- elseif b:ch == "'"
- call s:scanSingleQuote()
-
- " skip literal string
- elseif b:ch == '"'
- call s:scanDoubleQuote()
-
- elseif b:ch == '{'
- call s:scanChar()
- call s:gotoMatchEnd('{', '}')
-
- elseif b:ch == '('
- call s:scanChar()
- call s:gotoMatchEnd('(', ')')
-
- elseif b:ch == '['
- call s:scanChar()
- call s:gotoMatchEnd('[', ']')
-
- else
- " OAO
- call s:Match('[;({[/"'']')
- " OLD
- "call s:scanChar()
- endif
- endwhile
-endfu
-
-" s:Strpart(), s:Stridx(), s:Match() {{{2
-fu! Strpart(start, len)
- let startline = java_parser#DecodePos(a:start).line
- let endline = java_parser#DecodePos(a:start + a:len).line
- let str = join(b:lines[startline:endline-1]) . b:lines[endline]
- return strpart(str, a:start-b:idxes[startline], a:len)
-endfu
-
-fu! s:Stridx(needle)
- let found = 0
- while b:line < len(b:lines)-1
- let idx = stridx(b:lines[b:line], a:needle, b:col)
- if idx > -1
- let found = 1
- let b:col = idx
- break
- endif
- let b:line += 1
- let b:col = 0
- endwhile
-
- if found
- let b:bp = b:idxes[b:line] + b:col
- call s:scanChar()
- return b:bp
- else
- let b:bp = b:buflen
- let b:ch = s:EOI
- return -1
- endif
-endfu
-
-fu! s:Match(pat)
- let bp_old = b:bp
- let line_old = b:line
- let col_old = b:col
-
- let found = 0
- while b:line < len(b:lines)-1
- let idx = match(b:lines[b:line], a:pat, b:col)
- if idx > -1
- let found = 1
- let b:col = idx
- break
- endif
- let b:line += 1
- let b:col = 0
- endwhile
-
- if found
- let b:bp = b:idxes[b:line] + b:col-1
- call s:scanChar()
- return b:bp
- else
- let b:bp = bp_old
- let b:line = line_old
- let b:col = col_old
- call s:scanChar()
- return -1
- endif
-endfu
-
-
-" conversion between position and (line, col) {{{2
-fu! java_parser#MakePos(line, col)
- return b:idxes[a:line] + a:col
-endfu
-
-fu! java_parser#DecodePos(pos)
- let line = -1
- for idx in b:idxes
- if idx > a:pos
- break
- endif
- let line += 1
- endfor
- let col = a:pos - b:idxes[line]
- return {'line': line, 'col': col}
-endfu
-
-fu! s:Pos2Str(pos)
- let o = java_parser#DecodePos(a:pos)
- return '(' . (o.line+1) . ',' . (o.col+1) . ')'
-endfu
-
-" Bitwise operator emulators {{{1
-" NOTE: For more than 32 bit number, use the string bits form.
-
-" bit operator ~
-fu! s:BitNot(v)
- return s:Bits2Number( s:BitNot_binary(s:Number2Bits(a:v)) )
-endfu
-
-fu! s:BitNot_binary(v)
- let v = substitute(a:v, '^0*\([01]\+\)', '\1', 'g')
- let v = substitute(v, '1', '2', 'g')
- let v = substitute(v, '0', '1', 'g')
- let v = substitute(v, '2', '0', 'g')
- return v
-endfu
-
-" bit operator &
-fu! s:BitAnd(n1, n2)
- if a:n1 == 0 || a:n2 == 0 | return 0 | endif
- if a:n1 == a:n2 | return 1 | endif
- return s:Bits2Number( s:BitOperator_binary(s:Number2Bits(a:n1), s:Number2Bits(a:n2), 'n1[i] == "1" && n2[i] == "1"') )
-endfu
-
-" bit operator |
-fu! s:BitOr(n1, n2, ...)
- if a:0 == 0
- if a:n1 == 0
- return a:n2
- elseif a:n2 == 0
- return a:n1
- endif
- endif
- let result = s:BitOperator_binary(s:Number2Bits(a:n1), s:Number2Bits(a:n2), 'n1[i] == "1" || n2[i] == "1"')
- for a in a:000
- let result = s:BitOperator_binary(result, s:Number2Bits(a), 'n1[i] == "1" || n2[i] == "1"')
- endfor
- return s:Bits2Number( result )
-endfu
-
-" bit operator ^
-fu! s:BitXor(n1, n2)
- if a:n1 == a:n2 | return 0 | endif
- return s:Bits2Number( s:BitOperator_binary(s:Number2Bits(a:n1), s:Number2Bits(a:n2), 'n1[i] != n2[i]') )
-endfu
-
-fu! s:BitOperator_binary(n1, n2, comparator)
- let n1 = a:n1
- let n2 = a:n2
-
- let len1 = len(n1)
- let len2 = len(n2)
- let len = len1
- if len1 > len2
- let n2 = repeat('0', len1-len2) . n2
- else
- let len = len2
- let n1 = repeat('0', len2-len1) . n1
- endif
-
- let i = 0
- let bits = ''
- while i < len
- let bits .= eval(a:comparator) ? '1' : '0'
- let i += 1
- endwhile
- return bits
-endfu
-
-" bit operator <<
-fu! s:BitMoveLeft()
-endfu
-
-" bit operator >>
-fu! s:BitMoveRight()
-endfu
-
-" helper function: convert a number to a string consisted of '0' or '1' indicating number
-fu! s:Number2Bits(n, ...)
- if type(a:n) == type("") | return a:n | endif
- if a:n == 0 | return '0' | endif
-
- let n = a:n
- let bits = ''
- while n != 0
- let bit = n % 2
- "echo 'n: ' . n . ' bit: ' . bit
- let bits = bit . bits
- let n = (n-bit)/ 2
- endwhile
- if a:0 > 0
- let bits = repeat(a:1 - len(bits)) . bits
- endif
- return bits
-endfu
-
-" helper function: convert a string consisted of '0' or '1' indicating number to a number
-" precondition: bits must not be empty string
-fu! s:Bits2Number(bits)
- let len = len(a:bits)
- let n = a:bits[0]
- let i = 1
- while i < len
- let n = n * 2 + a:bits[i]
- let i += 1
- endwhile
- return n
-endfu
-
-
-let s:modifier_keywords = ['strictfp', 'abstract', 'interface', 'native', 'transient', 'volatile', 'synchronized', 'final', 'static', 'protected', 'private', 'public']
-fu! s:String2Flags(str)
- let mod = [0,0,0,0,0,0,0,0,0,0,0,0,]
- for item in split(a:str, '\s\+')
- if index(s:modifier_keywords, item) != -1
- let mod[index(s:modifier_keywords, item)] = '1'
- endif
- endfor
- return join(mod[index(mod, '1'):], '')
-endfu
-
-" Log utilities {{{1
-" level
-" 5 off/fatal
-" 4 error
-" 3 warn
-" 2 info
-" 1 debug
-" 0 trace
-fu! java_parser#SetLogLevel(level)
- let b:loglevel = a:level
-endfu
-
-fu! java_parser#GetLogLevel()
- return exists('b:loglevel') ? b:loglevel : 3
-endfu
-
-fu! java_parser#GetLogContent()
- return b:log
-endfu
-
-fu! s:Trace(msg)
- call s:Log(0, b:pos, a:msg)
-endfu
-
-fu! s:Debug(msg)
- call s:Log(1, b:pos, a:msg)
-endfu
-
-fu! s:Info(msg)
- call s:Log(2, b:pos, a:msg)
-endfu
-
-fu! s:Log(level, pos, key, ...)
- if a:level >= java_parser#GetLogLevel()
- echo a:key
- call add(b:log, a:key)
- endif
-endfu
-
-fu! s:ShowWatch(...)
- let at = a:0 > 0 ? a:1 : ''
- echo '-- b:bp ' . b:bp . string(java_parser#DecodePos(b:bp)) . ' b:ch "' . b:ch . '" b:name ' . b:name . ' b:token ' . b:token . ' b:pos ' .b:pos . ' endPos ' . b:endPos . ' prevEndPos ' . b:prevEndPos . ' errPos ' . b:errPos . ' errorEndPos ' . b:errorEndPos . at
-endfu
-
-fu! java_parser#Exe(cmd)
- exe a:cmd
-endfu
-
-" Parser {{{1
-" skip() Skip forward until a suitable stop token is found. {{{2
-fu! s:skip(stopAtImport, stopAtMemberDecl, stopAtIdentifier, stopAtStatement)
- while 1
- if b:token == 'SEMI'
- call s:nextToken()
- return
- elseif b:token =~# '^\(PUBLIC\|FINAL\|ABSTRACT\|MONKEYS_AT\|EOF\|CLASS\|INTERFACE\|ENUM\)$'
- return
- elseif b:token == 'IMPORT'
- if a:stopAtImport
- return
- endif
- elseif b:token =~# '^\(LBRACE\|RBRACE\|PRIVATE\|PROTECTED\|STATIC\|TRANSIENT\|NATIVE\|VOLATILE\|SYNCHRONIZED\|STRICTFP\|LT\|BYTE\|SHORT\|CHAR\|INT\|LONG\|FLOAT\|DOUBLE\|BOOLEAN\|VOID\)$'
- if a:stopAtMemberDecl
- return
- endif
- elseif b:token == 'IDENTIFIER'
- if a:stopAtIdentifier
- return
- endif
- elseif b:token =~# '^\(CASE\|DEFAULT\|IF\|FOR\|WHILE\|DO\|TRY\|SWITCH\|RETURN\|THROW\|BREAK\|CONTINUE\|ELSE\|FINALLY\|CATCH\)$'
- if a:stopAtStatement
- return
- endif
- endif
- call s:nextToken()
- endwhile
-endfu
-
-" syntax errors {{{2
-fu! s:SyntaxError(key, ...)
- let pos = a:0 == 0 ? b:pos : a:1
- let errs = a:0 > 1 ? a:2 : []
- call s:setErrorEndPos(pos)
- call s:ReportSyntaxError(pos, a:key)
- return {'tag': 'ERRONEOUS', 'pos': pos, 'errs': errs}
-endfu
-
-fu! s:ReportSyntaxError(pos, key, ...)
- if a:pos > b:errPos || a:pos == -1
- let key = a:key . (b:token == 'EOF' ? ' and premature.eof' : '')
- call s:Log(4, a:pos, '[syntax error]' . s:Pos2Str(a:pos) . ': ' . key)
- endif
- let b:errPos = a:pos
-endfu
-
-" accept() {{{2
-fu! s:accept(token_type)
- "call s:Debug(b:token . ' == ' . a:token_type . (b:token == a:token_type))
- if b:token == a:token_type
- call s:nextToken()
- else
- call s:setErrorEndPos(b:pos)
- call s:ReportSyntaxError(b:prevEndPos, s:token2string(a:token_type) . " expected")
- "call s:nextToken()
- endif
-endfu
-
-fu! s:token2string(token)
- if a:token =~# '^\(DOT\|COMMA\|SEMI\|LPAREN\|RPAREN\|LBRACKET\|RBRACKET\|LBRACE\|RBRACE\)$'
- return "'" . a:token . "'"
- endif
- return a:token
-endfu
-
-
-" illegal() {{{2
-fu! s:illegal(...)
- call s:setErrorEndPos(b:pos)
- return s:SyntaxError(s:modeAndEXPR() ? 'illegal.start.of.expr' : 'illegal.start.of.type', a:0 == 0 ? b:pos : a:1)
-endfu
-
-" setErrorEndPos() {{{2
-fu! s:setErrorEndPos(errPos)
- if a:errPos > b:errorEndPos
- let b:errorEndPos = a:errPos
- endif
-endfu
-
-" ident() {{{2
-" Ident = IDENTIFIER
-fu! s:ident()
- call s:Trace('s:ident ' . b:token)
-
- if b:token == 'IDENTIFIER'
- let name = b:name
- call s:nextToken()
- return name
-
- elseif b:token == 'ASSERT'
- if s:allowAsserts
- call s:Log(4, b:pos, 'assert.as.identifier')
- call s:nextToken()
- return '<error>'
- else
- call s:Log(3, b:pos, 'assert.as.identifier')
- let name = b:name
- call s:nextToken()
- return name
- endif
-
- elseif b:token == 'ENUM'
- if b:allowEnums
- call s:Log(4, b:pos, 'enum.as.identifier')
- call s:nextToken()
- return '<error>'
- else
- call s:Log(3, b:pos, 'enum.as.identifier')
- let name = b:name
- call s:nextToken()
- return name
- endif
-
- else
- call s:accept('IDENTIFIER')
- return '<error>'
- endif
-endfu
-
-" qualident() {{{2
-" Qualident = Ident { DOT Ident }
-fu! s:qualident()
- let t = s:Ident(b:pos, s:ident())
- while b:token == 'DOT'
- let pos = b:pos
- call s:nextToken()
- let t = s:Select(b:pos, t, s:ident())
- "let t.name .= '.' . s:ident() " FIXME
- endwhile
- return t
-endfu
-
-" literal() {{{2
-" Literal = INTLITERAL | LONGLITERAL | FLOATLITERAL | DOUBLELITERAL | CHARLITERAL | STRINGLITERAL | TRUE | FALSE | NULL
-fu! s:literal(prefix)
- let t = {'tag': 'LITERAL', 'pos': b:pos}
- if b:token == 'INTLITERAL'
- let t.typetag = 'INT'
- let t.value = b:sbuf
- elseif b:token == 'LONGLITERAL'
- let t.typetag = 'LONG'
- let t.value = b:sbuf
- elseif b:token == 'FLOATLITERAL'
- let t.typetag = 'FLOAT'
- let t.value = b:sbuf
- elseif b:token == 'DOUBLELITERAL'
- let t.typetag = 'DOUBLE'
- let t.value = b:sbuf
- elseif b:token == 'CHARLITERAL'
- let t.typetag = 'CHAR'
- let t.value = b:sbuf
- elseif b:token == 'STRINGLITERAL'
- let t.typetag = 'CLASS'
- let t.value = b:sbuf
- elseif b:token == 'TRUE'
- let t.typetag = 'BOOLEAN'
- let t.value = 1
- elseif b:token == 'FALSE'
- let t.typetag = 'BOOLEAN'
- let t.value = 0
- elseif b:token == 'NULL'
- let t.typetag = 'BOT'
- let t.value = 'null'
- else
- echoerr 'can not reach here'
- endif
- call s:nextToken()
- return t
-endfu
-
-" {{{2
-" terms, expression, type {{{2
-" When terms are parsed, the mode determines which is expected:
-" mode = EXPR : an expression
-" mode = TYPE : a type
-" mode = NOPARAMS : no parameters allowed for type
-" mode = TYPEARG : type argument
-let s:EXPR = 1
-let s:TYPE = 2
-let s:NOPARAMS = 4
-let s:TYPEARG = 8
-let s:EXPR_OR_TYPE = 3
-let s:EXPR_OR_TYPE_OR_NOPARAMS = 7
-let s:TYPEARG_OR_NOPARAMS = 12
-
-fu! s:modeAndEXPR()
- return b:mode % 2
-endfu
-
-fu! s:modeAndTYPE()
- return s:BitAnd(b:mode, s:TYPE)
-endfu
-
-" terms can be either expressions or types.
-fu! s:expression()
- return s:term(s:EXPR)
-endfu
-
-fu! s:type()
- return s:term(s:TYPE)
-endfu
-
-fu! s:typeList()
- let ts = []
- call add(ts, s:type())
- while b:token == 'COMMA'
- call s:nextToken()
- call add(ts, s:type())
- endwhile
- return ts
-endfu
-
-" Expression = Expression1 [ExpressionRest]
-" ExpressionRest = [AssignmentOperator Expression1]
-" AssignmentOperator = "=" | "+=" | "-=" | "*=" | "/=" | "&=" | "|=" | "^=" |
-" "%=" | "<<=" | ">>=" | ">>>="
-" Type = Type1
-" TypeNoParams = TypeNoParams1
-" StatementExpression = Expression
-" ConstantExpression = Expression
-fu! s:term(...)
- let prevmode = b:mode
- let b:mode = a:0 == 0 ? b:mode : a:1
-
- let t = s:term1()
- if s:modeAndEXPR() && b:token == 'EQ' || b:token =~# '^\(PLUSEQ\|SUBEQ\|STAREQ\|SLASHEQ\|AMPEQ\|BAREQ\|CARETEQ\|PERCENTEQ\|LTLTEQ\|GTGTEQ\|GTGTGTEQ\)$'
- let t = s:termRest(t)
- endif
-
- let b:lastmode = b:mode
- let b:mode = prevmode
- return t
-endfu
-
-fu! s:termRest(t)
- if b:token == 'EQ'
- let pos = b:pos
- call s:nextToken()
- let b:mode = s:EXPR
- return {'tag': 'ASSIGN', 'pos': pos, 'lhs': a:t, 'rhs': s:term()}
-
- elseif b:token =~# '^\(PLUSEQ\|SUBEQ\|STAREQ\|SLASHEQ\|PERCENTEQ\|AMPEQ\|BAREQ\|CARETEQ\|LTLTEQ\|GTGTEQ\|GTGTGTEQ\)$'
- let pos = b:pos
- let token = b:token
- call s:nextToken()
- let b:mode = s:EXPR
- return {'tag': s:optag(token), 'pos': pos, 'lhs': a:t, 'rhs': s:term()}
-
- else
- return a:t
- endif
-endfu
-
-" Expression1 = Expression2 [Expression1Rest]
-" Type1 = Type2
-" TypeNoParams1 = TypeNoParams2
-fu! s:term1()
- let t = s:term2()
- if s:modeAndEXPR() && b:token == 'QUES'
- let b:mode = s:EXPR
- return s:term1Rest(t)
- else
- return t
- endif
-endfu
-
-" Expression1Rest = ["?" Expression ":" Expression1]
-fu! s:term1Rest(t)
- if b:token == 'QUES'
- let t = {'tag': 'CONDEXPR', 'pos': b:pos, 'cond': a:t}
- call s:nextToken()
- let t.truepart = s:term()
- call s:accept('COLON')
- let t.falsepart = s:term1()
- return t
- else
- return a:t
- endif
-endfu
-
-" Expression2 = Expression3 [Expression2Rest]
-" Type2 = Type3
-" TypeNoParams2 = TypeNoParams3
-fu! s:term2()
- let t = s:term3()
- if s:modeAndEXPR() && s:prec(b:token) >= s:opprecedences.orPrec
- let b:mode = s:EXPR
- return s:term2Rest(t, s:opprecedences.orPrec)
- else
- return t
- endif
-endfu
-
-" Expression2Rest = {infixop Expression3}
-"" | Expression3 instanceof Type
-" infixop = "||"
-" | "&&"
-" | "|"
-" | "^"
-" | "&"
-" | "==" | "!="
-" | "<" | ">" | "<=" | ">="
-" | "<<" | ">>" | ">>>"
-" | "+" | "-"
-" | "*" | "/" | "%"
-fu! s:term2Rest(t, minprec)
- let odStack = [a:t] " for expressions
- let opStack = [] " for tokens
- let top = 0
- let startPos = b:pos
- let topOp = 'ERROR'
- while s:prec(b:token) >= a:minprec
- call add(opStack, topOp)
- let top += 1
- let topOp = b:token
- let pos = b:pos
- call s:nextToken()
- call add(odStack, topOp == 'INSTANCEOF' ? s:type() : s:term3())
- while top > 0 && s:prec(topOp) >= s:prec(b:token)
- let odStack[top-1] = s:makeOp(pos, topOp, odStack[top-1], odStack[top])
- let top -= 1
- let topOp = opStack[top]
- endwhile
- endwhile
- "assert top == 0
- let t = odStack[0]
-
- if t.tag == 'PLUS'
- let buf = s:foldStrings(t)
- if buf != ''
- let t = {'tag': 'LITERAL', 'pos': startPos, 'typetag': 'CLASS', 'value': t}
- endif
- endif
- return t
-endfu
-
-fu! s:makeOp(pos, topOp, od1, od2)
- if a:topOp == 'INSTANCEOF'
- return {'tag': 'TYPETEST', 'pos': a:pos, 'expr': a:od1, 'clazz': a:od2}
- else
- return s:Binary(a:pos, s:optag(a:topOp), a:od1, a:od2)
- endif
-endfu
-
-fu! s:foldStrings(tree)
- let tree = a:tree
- let buf = ''
- while 1
- if tree.tag == 'LITERAL'
- let lit = tree
- if lit.typetag == 'CLASS'
- let sbuf = lit.value
- if buf != ''
- let sbuf .= buf
- endif
- return sbuf
- endif
- elseif tree.tag == 'PLUS'
- let op = tree
- if op.rhs.tag == 'LITERAL'
- let lit = op.rhs
- if lit.typetag == 'CLASS'
- let buf = lit.value . buf
- let tree = op.lhs
- continue
- endif
- endif
- endif
- return ''
- endwhile
-endfu
-
-" Expression3 = PrefixOp Expression3 {{{2
-" | "(" Expr | TypeNoParams ")" Expression3
-" | Primary {Selector} {PostfixOp}
-" Primary = "(" Expression ")"
-" | Literal
-" | [TypeArguments] THIS [Arguments]
-" | [TypeArguments] SUPER SuperSuffix
-" | NEW [TypeArguments] Creator
-" | Ident { "." Ident }
-" [ "[" ( "]" BracketsOpt "." CLASS | Expression "]" )
-" | Arguments
-" | "." ( CLASS | THIS | [TypeArguments] SUPER Arguments | NEW [TypeArguments] InnerCreator )
-" ]
-" | BasicType BracketsOpt "." CLASS
-" PrefixOp = "++" | "--" | "!" | "~" | "+" | "-"
-" PostfixOp = "++" | "--"
-" Type3 = Ident { "." Ident } [TypeArguments] {TypeSelector} BracketsOpt
-" | BasicType
-" TypeNoParams3 = Ident { "." Ident } BracketsOpt
-" Selector = "." [TypeArguments] Ident [Arguments]
-" | "." THIS
-" | "." [TypeArguments] SUPER SuperSuffix
-" | "." NEW [TypeArguments] InnerCreator
-" | "[" Expression "]"
-" TypeSelector = "." Ident [TypeArguments]
-" SuperSuffix = Arguments | "." Ident [Arguments]
-" NOTE: We need only type expression.
-fu! s:term3()
- let pos = b:pos
- let t = copy(s:TTree)
-
- call s:Debug('term3() b:token is ' . b:token)
- let typeArgs = s:typeArgumentsOpt(s:EXPR)
-
- if b:token == 'QUES'
- if s:modeAndTYPE() && s:BitAnd(b:mode, s:TYPEARG_OR_NOPARAMS) == s:TYPEARG
- let b:mode = s:TYPE
- return s:typeArgument()
- else
- return s:illegal()
- endif
-
- elseif b:token =~# '^\(PLUSPLUS\|SUBSUB\|BANG\|TILDE\|PLUS\|SUB\)$'
- if typeArgs == [] && s:modeAndEXPR()
- let token = b:token
- call s:nextToken()
- let b:mode = s:EXPR
- if token == 'SUB' && (b:token == 'INTLITERAL' || b:token == 'LONGLITERAL') && b:radix == 10
- let b:mode = s:EXPR
- let t = s:literal('-')
- else
- let t = s:term3()
- return s:Unary(pos, s:unoptag(token), t)
- endif
- else
- return s:illegal()
- endif
-
- elseif b:token == 'LPAREN'
- if typeArgs == [] && s:modeAndEXPR()
- call s:nextToken()
- let b:mode = s:EXPR_OR_TYPE_OR_NOPARAMS
- let t = s:term3()
- if s:modeAndEXPR() && b:token == 'LT'
- let op = 'LT'
- let pos1 = b:pos
- call s:nextToken()
- let b:mode = s:BitAnd(b:mode, s:EXPR_OR_TYPE)
- let b:mode = s:BitOr(b:mode, s:TYPEARG)
- let t1 = s:term3()
- if s:modeAndTYPE() && (b:token == 'COMMA' || b:token == 'GT')
- let b:mode = s:TYPE
- let args = []
- call add(args, t1)
- while b:token == 'COMMA'
- call s:nextToken()
- call add(args, s:typeArgument())
- endwhile
- call s:accept('GT')
- let t = {'tag': 'TYPEAPPLY', 'pos': pos1, 'clazz': t, 'arguments': args}
- " checkGenerics
- let t = s:bracketsOpt(t)
- elseif s:modeAndEXPR()
- let b:mode = s:EXPR
- let t = s:Binary(pos1, op, t, s:term2Rest(t1, s:opprecedences.shiftPrec))
- let t = s:termRest(s:term1Rest(s:term2Rest(t, s:opprecedences.orPrec)))
- else
- call s:accept('GT')
- endif
- else
- let t = s:termRest(s:term1Rest(s:term2Rest(t, s:opprecedences.orPrec)))
- endif
- call s:accept('RPAREN')
- let b:lastmode = b:mode
- let b:mode = s:EXPR
- if s:BitAnd(b:lastmode, s:EXPR) == 0
- return s:TypeCast(pos, t, s:term3())
- elseif s:BitAnd(b:lastmode, s:TYPE) != 0
- if b:token =~# '^\(BANG\|TILDE\|LPAREN\|THIS\|SUPER\|INTLITERAL\|LONGLITERAL\|FLOATLITERAL\|DOUBLELITERAL\|CHARLITERAL\|STRINGLITERAL\|TRUE\|FALSE\|NULL\|NEW\|IDENTIFIER\|ASSERT\|ENUM\|BYTE\|SHORT\|CHAR\|INT\|LONG\|FLOAT\|DOUBLE\|BOOLEAN\|VOID\)$'
- return s:TypeCast(pos, t, s:term3())
- endif
- endif
- else
- return s:illegal()
- endif
- let t = {'tag': 'PARENS', 'pos': pos, 'expr': t}
-
- elseif b:token == 'THIS'
- if s:modeAndEXPR()
- let b:mode = s:EXPR
- let t = s:Ident(pos, 'this')
- call s:nextToken()
- if typeArgs == []
- let t = s:argumentsOpt([], t)
- else
- let t = s:arguments(typeArgs, t)
- endif
- let typeArgs = []
- else
- return s:illegal()
- endif
-
- elseif b:token == 'SUPER'
- if s:modeAndEXPR()
- let b:mode = s:EXPR
- let t = s:superSuffix(typeArgs, s:Ident(pos, 'super'))
- let typeArgs = []
- else
- return s:illegal()
- endif
-
- elseif b:token =~# '^\(INTLITERAL\|LONGLITERAL\|FLOATLITERAL\|DOUBLELITERAL\|CHARLITERAL\|STRINGLITERAL\|TRUE\|FALSE\|NULL\)$'
- if typeArgs == [] && s:modeAndEXPR()
- let b:mode = s:EXPR
- let t = s:literal('')
- else
- return s:illegal()
- endif
-
- elseif b:token == 'NEW'
- if typeArgs != []
- return s:illegal()
- endif
-
- if s:modeAndEXPR()
- let b:mode = s:EXPR
- call s:nextToken()
- if b:token == 'LT'
- let typeArgs = s:typeArguments()
- endif
- let t = s:creator(pos, typeArgs)
- let typeArgs = []
- else
- return s:illegal()
- endif
-
- elseif b:token =~# '^\(IDENTIFIER\|ASSERT\|ENUM\)$'
- if typeArgs != []
- return s:illegal()
- endif
-
- let t = s:Ident(pos, s:ident())
- while 1
- if b:token == 'LBRACKET'
- "let t.value = '[' " FIXME
- call s:nextToken()
- if b:token == 'RBRACKET'
- "let t.value .= ']'
- call s:nextToken()
- let t = s:bracketsSuffix(s:TypeArray(pos, s:bracketsOpt(t)))
- else
- if s:modeAndEXPR()
- let b:mode = s:EXPR
- let t = {'tag': 'INDEXED', 'pos': pos, 'indexed': t, 'index': s:term()}
- endif
- call s:accept('RBRACKET')
- "let t.value .= ']'
- endif
- break
-
- elseif b:token == 'LPAREN'
- if s:modeAndEXPR()
- let b:mode = s:EXPR
- let t = s:arguments(typeArgs, t)
- let typeArgs = []
- "call s:accept('LPAREN')
- "call s:gotoMatchEnd('(', ')', b:token == 'LPAREN')
- "call s:accept('RPAREN')
- endif
- break
-
- elseif b:token == 'DOT'
- call s:nextToken()
- let typeArgs = s:typeArgumentsOpt(s:EXPR)
- if s:modeAndEXPR()
- if b:token == 'CLASS' || b:token == 'THIS'
- if typeArgs != []
- return s:illegal()
- endif
- let b:mode = s:EXPR
- let t = s:Select(pos, t, b:token == 'CLASS' ? 'class' : 'this')
- call s:nextToken()
- break
- elseif b:token == 'SUPER'
- let b:mode = s:EXPR
- let t = s:Select(pos, t, 'super')
- let t = s:superSuffix(typeArgs, t)
- let typeArgs = []
- break
- elseif b:token == 'NEW'
- if typeArgs != []
- return s:illegal()
- endif
- let b:mode = s:EXPR
- let pos1 = b:pos
- call s:nextToken()
- if b:token == 'LT'
- let typeArgs = s:typeArguments()
- endif
- let t = s:innerCreator(pos1, typeArgs, t)
- let typeArgs = []
- break
- endif
- endif
- let t = s:Select(pos, t, s:ident())
- else
- break
- endif
- endwhile
- if typeArgs != [] | call s:illegal() | endif
- let t = s:typeArgumentsOpt2(t)
-
- elseif b:token =~# '^\(BYTE\|SHORT\|CHAR\|INT\|LONG\|FLOAT\|DOUBLE\|BOOLEAN\)$'
- if typeArgs != [] | call s:illegal() | endif
- let t = s:bracketsSuffix(s:bracketsOpt(s:basicType()))
-
- elseif b:token == 'VOID'
- if typeArgs != [] | call s:illegal() | endif
- if s:modeAndEXPR()
- call s:nextToken()
- if b:token == 'DOT'
- let ti = {'tag': 'TYPEIDENT', 'pos': pos, 'typetag': 'void'} " FIXME
- let t = s:bracketsSuffix(ti)
- else
- return s:illegal(pos)
- endif
- else
- return s:illegal()
- endif
-
- else
- return s:illegal()
- endif
-
- if typeArgs != []
- return s:illegal()
- endif
-
- while 1
- let pos1 = b:pos
- if b:token == 'LBRACKET'
- call s:nextToken()
- if s:modeAndEXPR()
- let oldmode = b:mode
- let b:mode = s:TYPE
- if b:token == 'RBRACKET'
- call s:nextToken()
- let t = s:bracketsOpt(t)
- let t = s:TypeArray(pos1, t)
- return t
- endif
- let b:mode = oldmode
- endif
- if s:modeAndEXPR()
- let b:mode = s:EXPR
- let t = {'tag': 'INDEXED', 'pos': pos1, 'indexed': t, 'index': s:term()}
- endif
- call s:accept('RBRACKET')
-
- elseif b:token == 'DOT'
- call s:nextToken()
- let typeArgs = s:typeArgumentsOpt(s:EXPR)
- if b:token == 'SUPER' && s:modeAndEXPR()
- let b:mode = s:EXPR
- let t = s:Select(pos1, t, 'super')
- call s:nextToken()
- let t = s:arguments(typeArgs, t)
- let typeArgs = []
- elseif b:token == 'NEW' && s:modeAndEXPR()
- if typeArgs != []
- return s:illegal()
- endif
- let b:mode = s:EXPR
- let pos2 = b:pos
- call s:nextToken()
- if b:token == 'LT'
- let typeArgs = s:typeArguments()
- endif
- let t = s:innerCreator(pos2, typeArgs, t)
- let typeArgs = []
- else
- let t = s:Select(pos1, t, s:ident())
- let t = s:argumentsOpt(typeArgs, s:typeArgumentsOpt2(t))
- let typeArgs = []
- endif
- else
- break
- endif
- endwhile
-
-
- while (b:token == 'PLUSPLUS' || b:token == 'SUBSUB') && s:modeAndEXPR()
- let b:mode = s:EXPR
- let t = s:Unary(b:pos, b:token == 'PLUSPLUS' ? 'POSTINC' : 'POSTDEC', t)
- call s:nextToken()
- endwhile
- return t
-endfu
-
-fu! s:superSuffix(typeArgs, t)
- let typeArgs = a:typeArgs
- let t = a:t
- call s:nextToken()
- if b:token == 'LPAREN' || typeArgs != []
- let t = s:arguments(typeArgs, t)
- else
- let pos = b:pos
- call s:accept('DOT')
- let typeArgs = b:token == 'LT' ? s:typeArguments() : []
- let t = s:Select(pos, t, s:ident())
- let t = s:argumentsOpt(typeArgs, t)
- endif
- return t
-endfu
-
-" BasicType = BYTE | SHORT | CHAR | INT | LONG | FLOAT | DOUBLE | BOOLEAN {{{2
-fu! s:basicType()
- let t = {'tag': 'TYPEIDENT', 'pos': b:pos, 'typetag': s:typetag(b:token)}
- call s:nextToken()
- return t
-endfu
-
-" ArgumentsOpt = [ Arguments ] {{{2
-fu! s:argumentsOpt(typeArgs, t)
- if s:modeAndEXPR() && b:token == 'LPAREN' || a:typeArgs != []
- let b:mode = s:EXPR
- return s:arguments(a:typeArgs, a:t)
- else
- return a:t
- endif
-endfu
-
-" Arguments = "(" [Expression { COMMA Expression }] ")"
-fu! s:arguments(...)
- let pos = b:pos
- let args = []
- if b:token == 'LPAREN'
- call s:nextToken()
- if b:token != 'RPAREN'
- call add(args, s:expression())
- while b:token == 'COMMA'
- call s:nextToken()
- call add(args, s:expression())
- endwhile
- endif
- call s:accept('RPAREN')
- else
- call s:SyntaxError(') expected')
- endif
-
- if a:0 == 0
- return args
- else
- let typeArgs = a:1
- let t = a:2
- return {'tag': 'APPLY', 'pos': pos, 'typeargs': typeArgs, 'meth': t, 'args': args}
- endif
-endfu
-
-" typeArgument generic type {{{2
-fu! s:typeArgumentsOpt2(t)
- if b:token == 'LT' && s:modeAndTYPE() && s:BitAnd(b:mode, s:NOPARAMS) == 0
- let b:mode = s:TYPE
- " checkGenerics()
- return s:typeArguments(a:t)
- else
- return a:t
- endif
-endfu
-
-fu! s:typeArgumentsOpt(...)
- let useMode = a:0 == 0 ? s:TYPE : a:1
-
- if b:token == 'LT'
- " checkGenerics()
- if s:BitAnd(b:mode, useMode) == 0 || s:BitAnd(b:mode, s:NOPARAMS) != 0
- return s:illegal()
- endif
- let b:mode = useMode
- return s:typeArguments()
- endif
- return []
-endfu
-
-" TypeArguments = "<" TypeArgument {"," TypeArgument} ">"
-fu! s:typeArguments(...)
- let pos = b:pos
-
- let args = []
- if b:token == 'LT'
- call s:nextToken()
- call add(args, s:modeAndEXPR() ? s:type() : s:typeArgument())
- while b:token == 'COMMA'
- call s:nextToken()
- call add(args, s:modeAndEXPR() ? s:type() : s:typeArgument())
- endwhile
-
- if b:token == 'GTGTGTEQ'
- let b:token = 'GTGTEQ'
- elseif b:token == 'GTGTEQ'
- let b:token = 'GTEQ'
- elseif b:token == 'GTEQ'
- let b:token = 'EQ'
- elseif b:token == 'GTGTGT'
- let b:token = 'GTGT'
- elseif b:token == 'GTGT'
- let b:token = 'GT'
- else
- call s:accept('GT')
- endif
- else
- call s:SyntaxError("LT expected")
- endif
-
- if a:0 == 0
- return args
- else
- return {'tag': 'TYPEAPPLY', 'pos': pos, 'clazz': a:1, 'arguments': args}
- endif
-endfu
-
-" TypeArgument = Type
-" | "?"
-" | "?" EXTENDS Type {"&" Type}
-" | "?" SUPER Type
-fu! s:typeArgument()
- if b:token != 'QUES'
- return s:type()
- endif
-
- call s:nextToken()
- if b:token == 'EXTENDS'
- call s:nextToken()
- return s:type()
- elseif b:token == 'SUPER'
- call s:nextToken()
- return s:type()
- elseif b:token == 'IDENTIFIER'
- let id = ident()
- else
- endif
-endfu
-
-
-" BracketsOpt = {"[" "]"} {{{2
-fu! s:bracketsOpt(t)
- let t = a:t
- while b:token == 'LBRACKET'
- let pos = b:pos
- call s:nextToken()
- let t = s:bracketsOptCont(t, pos)
- endwhile
- return t
-endfu
-
-fu! s:bracketsOptCont(t, pos)
- let t = a:t
- call s:accept('RBRACKET')
- let t = s:bracketsOpt(t)
- return s:TypeArray(a:pos, t)
-endfu
-
-" BracketsSuffixExpr = "." CLASS
-" BracketsSuffixType =
-fu! s:bracketsSuffix(t)
- let t = a:t
- if s:modeAndEXPR() && b:token == 'DOT'
- let b:mode = s:EXPR
- let pos = b:pos
- call s:nextToken()
- call s:accept('CLASS')
- if b:pos == b:errorEndPos
- let name = ''
- if b:token == 'IDENTIFIER'
- let name = b:name
- call s:nextToken()
- else
- let name = '<error>'
- endif
- let t = {'tag': 'ERRONEOUS', 'pos': pos, 'errs': [s:Select(pos, t, name)]}
- else
- let t = s:Select(pos, t, 'class')
- endif
- elseif s:modeAndTYPE()
- let b:mode = s:TYPE
- else
- call s:SyntaxError('dot.class.expected')
- endif
- return t
-endfu
-
-" creator {{{2
-fu! s:creator(newpos, typeArgs)
- if b:token =~# '^\(BYTE\|SHORT\|CHAR\|INT\|LONG\|FLOAT\|DOUBLE\|BOOLEAN\)$'
- if a:typeArgs == []
- return s:arrayCreatorRest(a:newpos, s:basicType())
- endif
- endif
-
- let t = s:qualident()
- let oldmode = b:mode
- let b:mode = s:TYPE
- if b:token == 'LT'
- "checkGenerics
- let t = s:typeArguments(t)
- endif
- let b:mode = oldmode
-
- if b:token == 'LBRACKET'
- return s:arrayCreatorRest(a:newpos, t)
- elseif b:token == 'LPAREN'
- return s:classCreatorRest(a:newpos, {}, a:typeArgs, t)
- else
- call s:ReportSyntaxError(b:pos, '( or [ expected')
- let t = {'tag': 'NEWCLASS', 'encl': {}, 'typeargs': a:typeArgs, 'clazz': t, 'args': [], 'def': {}}
- return {'tag': 'ERRONEOUS', 'pos': a:newpos, 'errs': [t]}
- endif
-endfu
-
-fu! s:innerCreator(newpos, typeArgs, encl)
- let t = s:Ident(b:pos, s:ident())
- if b:token == 'LT'
- " checkGenerics
- let t = TypeArguments(t)
- endif
- return s:classCreatorRest(a:newpos, a:encl, a:typeArgs, t)
-endfu
-
-fu! s:arrayCreatorRest(newpos, elemtype)
- let elemtype = a:elemtype
- call s:accept('LBRACKET')
- if b:token == 'RBRACKET'
- call s:accept('RBRACKET')
- let elemtype = s:bracketsOpt(elemtype)
- if b:token == 'LBRACE'
- return s:arrayInitializer(a:newpos, elemtype)
- else
- return s:SyntaxError('array.dimension.missing')
- endif
- else
- let dims = [s:expression()]
- call s:accept('RBRACKET')
- while b:token == 'LBRACKET'
- let pos = b:pos
- call s:nextToken()
- if b:token == 'RBRACKET'
- let elemtype = s:bracketsOptCont(elemtype, pos)
- else
- call add(dims, s:expression())
- call s:accept('RBRACKET')
- endif
- endwhile
- return {'tag': 'NEWARRAY', 'pos': a:newpos, 'elemtype': elemtype, 'dims': dims, 'elems': {}}
- endif
-endfu
-
-fu! s:classCreatorRest(newpos, encl, typeArgs, t)
- let args = s:arguments()
- let body = {}
- if b:token == 'LBRACE'
- let body = s:ClassDef(b:pos, {})
- let body.defs = s:classOrInterfaceBody('', 0)
- let body.endpos = b:pos
- endif
- return {'tag': 'NEWCLASS', 'encl': a:encl, 'typeargs': a:typeArgs, 'clazz': a:t, 'args': args, 'def': body}
-endfu
-
-" ArrayInitializer = "{" [VariableInitializer {"," VariableInitializer}] [","] "}" {{{2
-fu! s:arrayInitializer(newpos, t)
- call s:accept('LBRACE')
- let elems = []
- if b:token == 'COMMA'
- call s:nextToken()
- elseif b:token != 'RBRACE'
- call add(elems, s:variableInitializer())
- while b:token == 'COMMA'
- call s:nextToken()
- if b:token == 'RBRACE'
- break
- endif
- call add(elems, s:variableInitializer())
- endwhile
- endif
- call s:accept('RBRACE')
- return {'tag': 'NEWARRAY', 'pos': a:newpos, 'elemtype': a:t, 'dims': [], 'elems': elems}
-endfu
-
-" VariableInitializer = ArrayInitializer | Expression {{{2
-fu! s:variableInitializer()
- return b:token == 'LBRACE' ? s:arrayInitializer(b:pos, {}) : s:expression()
-endfu
-
-" ParExpression = "(" Expression ")" {{{2
-fu! s:parExpression()
- call s:accept('LPAREN')
- let t = s:expression()
- call s:accept('RPAREN')
- return t
-endfu
-
-" {{{2
-" Block = "{" BlockStatements "}" {{{2
-fu! s:block(...)
- let t = {'tag': 'BLOCK', 'stats': []}
- let t.pos = a:0 > 0 ? a:1 : b:pos
- let t.flags = a:0 > 1 ? a:2 : 0
-
- call s:accept('LBRACE')
-
- " scan strategy: ignore statements?
- if a:0 > 2 && a:3
- if b:token !=# 'RBRACE'
- let b:pos = s:gotoMatchEnd('{', '}', b:token == 'LBRACE')
- endif
- "let t.stats = Strpart(t.pos, t.endpos-t.pos-1)
- else
- let t.stats = s:blockStatements()
- while b:token == 'CASE' || b:token == 'DEFAULT'
- call s:SyntaxError("orphaned")
- call s:switchBlockStatementGroups()
- endwhile
- endif
-
- let t.endpos = b:pos
- call s:accept('RBRACE')
- return t
-endfu
-
-" BlockStatements = { BlockStatement } {{{2
-" BlockStatement = LocalVariableDeclarationStatement
-" | ClassOrInterfaceOrEnumDeclaration
-" | [Ident ":"] Statement
-" LocalVariableDeclarationStatement
-" = { FINAL | '@' Annotation } Type VariableDeclarators ";"
-fu! s:blockStatements()
- let lastErrPos = -1
- let stats = []
- while 1
- let pos = b:pos
- if b:token =~# '^\(RBRACE\|CASE\|DEFAULT\|EOF\)$'
- return stats
- elseif b:token =~# '^\(LBRACE\|IF\|FOR\|WHILE\|DO\|TRY\|SWITCH\|SYNCHRONIZED\|RETURN\|THROW\|BREAK\|CONTINUE\|SEMI\|ELSE\|FINALLY\|CATCH\)$'
- call add(stats, s:statement())
- elseif b:token =~# '^\(MONKEYS_AT\|FINAL\)'
- let dc = b:docComment
- let mods = s:modifiersOpt()
- if b:token =~# '^\(INTERFACE\|CLASS\|ENUM\)$'
- call add(stats, s:classOrInterfaceOrEnumDeclaration(mods, dc))
- else
- let t = s:type()
- let stats = stats + s:variableDeclarators(mods, t, [])
- call s:accept('SEMI')
- endif
- elseif b:token =~# '^\(ABSTRACT\|STRICTFP\|CLASS\|INTERFACE\|ENUM\)$'
- if b:token == 'ENUM'
- call s:Log(4, b:pos, 'local.enum')
- endif
- call add(stats, s:classOrInterfaceOrEnumDeclaration(s:modifiersOpt(), b:docComment))
- elseif b:token == 'ASSERT'
- call add(stats, s:statement())
- else
- let name = b:name
- let t = s:term(s:EXPR_OR_TYPE)
- if b:token == 'COLON' && t.tag == 'IDENT'
- call s:nextToken()
- let stat = s:statement()
- call add(stats, {'tag': 'LABELLED', 'pos': b:pos, 'label': name, 'body': stat})
- elseif s:BitAnd(b:lastmode, s:TYPE) && b:token =~# '^\(IDENTIFIER\|ASSERT\|ENUM\)$'
- let pos = b:pos
- let mods = {} " {'tag': 'MODIFIERS', 'pos': -1, 'flags': 0}
- let stats = stats + s:variableDeclarators(mods, t, [])
- call s:accept('SEMI')
- else
- call add(stats, {'tag': 'EXEC', 'pos': pos, 'expr': s:checkExprStat(t)}) " TODO
- call s:accept('SEMI')
- endif
- endif
-
- if b:pos == lastErrPos
- return stats
- endif
- if b:pos <= b:errorEndPos
- call s:skip(0, 1, 1, 1)
- let lastErrPos = b:pos
- endif
-
- " resetDeprecatedFlag()
- endwhile
-endfu
-
-" Statement = Block {{{2
-" | IF ParExpression Statement [ELSE Statement]
-" | FOR "(" ForInitOpt ";" [Expression] ";" ForUpdateOpt ")" Statement
-" | FOR "(" FormalParameter : Expression ")" Statement
-" | WHILE ParExpression Statement
-" | DO Statement WHILE ParExpression ";"
-" | TRY Block ( Catches | [Catches] FinallyPart )
-" | SWITCH ParExpression "{" SwitchBlockStatementGroups "}"
-" | SYNCHRONIZED ParExpression Block
-" | RETURN [Expression] ";"
-" | THROW Expression ";"
-" | BREAK [Ident] ";"
-" | CONTINUE [Ident] ";"
-" | ASSERT Expression [ ":" Expression ] ";"
-" | ";"
-" | ExpressionStatement
-" | Ident ":" Statement
-" called only by BlockStatements or self
-fu! s:statement()
- let pos = b:pos
- if b:token == 'LBRACE'
- return s:block()
- elseif b:token == 'IF'
- call s:nextToken()
- let t = {'tag': 'IF', 'pos': pos, 'cond': s:parExpression(), 'thenpart': s:statement()}
- if b:token == 'ELSE'
- call s:nextToken()
- let t.elsepart = s:statement()
- endif
- let t.endpos = b:pos
- return t
-
- elseif b:token == 'FOR'
- call s:nextToken()
- call s:accept('LPAREN')
- let inits = b:token == 'SEMI' ? [] : s:forInit()
- " foreach
- if len(inits) == 1 && inits[0].tag == 'VARDEF' && (!has_key(inits[0], 'init') || inits[0].init == {}) && b:token == 'COLON'
- " checkForeach
- let var = inits[0]
- call s:accept('COLON')
- let expr = s:expression()
- call s:accept('RPAREN')
- let body = s:statement()
- return {'tag': 'FOREACHLOOP', 'pos': pos, 'endpos': b:pos, 'var': var, 'expr': expr, 'body': body}
- else
- call s:accept('SEMI')
- let cond = b:token == 'SEMI' ? {} : s:expression()
- call s:accept('SEMI')
- let steps = b:token == 'RPAREN' ? [] : s:forUpdate()
- call s:accept('RPAREN')
- let body = s:statement()
- return {'tag': 'FORLOOP', 'pos': pos, 'endpos': b:pos, 'init': inits, 'cond': cond, 'step': steps, 'body': body}
- endif
-
- elseif b:token == 'WHILE'
- call s:nextToken()
- let cond = s:parExpression()
- let body = s:statement()
- return {'tag': 'WHILELOOP', 'pos': pos, 'endpos': b:pos, 'cond': cond, 'body': body}
-
- elseif b:token == 'DO'
- call s:nextToken()
- let body = s:statement()
- call s:accept('WHILE')
- let cond = s:parExpression()
- let t = {'tag': 'DOLOOP', 'pos': pos, 'endpos': b:pos, 'cond': cond, 'body': body}
- call s:accept('SEMI')
- return t
-
- elseif b:token == 'TRY'
- call s:nextToken()
- let body = s:block()
- let catchers = []
- let finalizer = {}
- if b:token == 'CATCH' || b:token == 'FINALLY'
- while b:token == 'CATCH'
- call add(catchers, s:catchClause())
- endwhile
- if b:token == 'FINALLY'
- call s:nextToken()
- let finalizer = s:block()
- endif
- else
- call s:Log(4, b:pos, 'try.without.catch.or.finally')
- endif
- return {'tag': 'TRY', 'pos': pos, 'endpos': b:pos, 'body': body, 'catchers': catchers, 'finalizer': finalizer}
-
- elseif b:token == 'SWITCH'
- call s:nextToken()
- let selector = s:parExpression()
- call s:accept('LBRACE')
- let cases = s:switchBlockStatementGroups()
- call s:accept('RBRACE')
- return {'tag': 'SWITCH', 'pos': pos, 'endpos': b:pos, 'selector': selector, 'cases': cases}
-
- elseif b:token == 'SYNCHRONIZED'
- call s:nextToken()
- let lock = s:parExpression()
- let body = s:block()
- return {'tag': 'SYNCHRONIZED', 'pos': pos, 'endpos': b:pos, 'lock': lock, 'cases': body}
-
- elseif b:token == 'RETURN'
- call s:nextToken()
- let result = b:token == 'SEMI' ? {} : s:expression()
- call s:accept('SEMI')
- return {'tag': 'RETURN', 'pos': pos, 'endpos': b:pos, 'expr': result}
-
- elseif b:token == 'THROW'
- call s:nextToken()
- let exc = s:expression()
- call s:accept('SEMI')
- return {'tag': 'THROW', 'pos': pos, 'endpos': b:pos, 'expr': exc}
-
- elseif b:token == 'BREAK' || b:token == 'CONTINUE'
- let token = b:token
- call s:nextToken()
- let label = b:token =~# '^\(IDENTIFIER\|ASSERT\|ENUM\)$' ? s:ident() : ''
- call s:accept('SEMI')
- return {'tag': token, 'pos': pos, 'endpos': b:pos, 'label': label}
-
- elseif b:token == 'SEMI'
- call s:nextToken()
- return {'tag': 'SKIP', 'pos': pos}
-
- elseif b:token == 'ELSE'
- return s:SyntaxError("else.without.if")
- elseif b:token == 'FINALLY'
- return s:SyntaxError("finally.without.try")
- elseif b:token == 'CATCH'
- return s:SyntaxError("catch.without.try")
-
- elseif b:token == 'ASSERT'
- "if b:allowAsserts && b:token == 'ASSERT'
- call s:nextToken()
- let t = {'tag': 'ASSERT', 'pos': pos, 'cond': s:expression()}
- if b:token == 'COLON'
- call s:nextToken()
- let t.detail = s:expression()
- endif
- call s:accept('SEMI')
- let t.endpos = b:pos
- return t
- "endif
-
- else " also ENUM
- let name = b:name
- let expr = s:expression()
- if b:token == 'COLON' && expr.tag == 'IDENT'
- call s:nextToken()
- let stat = s:statement()
- return {'tag': 'LABELLED', 'pos': pos, 'endpos': b:pos, 'label': name, 'body': stat}
- else
- let stat = {'tag': 'EXEC', 'pos': pos, 'endpos': b:pos, 'expr': s:checkExprStat(expr)}
- call s:accept('SEMI')
- return stat
- endif
- endif
-endfu
-
-" CatchClause = CATCH "(" FormalParameter ")" Block
-fu! s:catchClause()
- let pos = b:pos
- call s:accept('CATCH')
- call s:accept('LPAREN')
- let formal = s:variableDeclaratorId(s:optFinalParameter(), s:qualident())
- call s:accept('RPAREN')
- let body = s:block()
- return {'tag': 'CATCH', 'pos': pos, 'endpos': b:pos, 'param': formal, 'body': body}
-endfu
-
-" SwitchBlockStatementGroups = { SwitchBlockStatementGroup }
-" SwitchBlockStatementGroup = SwitchLabel BlockStatements
-" SwitchLabel = CASE ConstantExpression ":" | DEFAULT ":"
-fu! s:switchBlockStatementGroups()
- let cases = []
- while 1
- let pos = b:pos
- if b:token == 'CASE' || b:token == 'DEFAULT'
- let token = b:token
- call s:nextToken()
- let pat = token == 'CASE' ? s:expression() : {}
- call s:accept('COLON')
- let stats = s:blockStatements()
- call add(cases, {'tag': 'CASE', 'pos': pos, 'pat': pat, 'stats': stats})
- elseif b:token == 'RBRACE' || b:token == 'EOF'
- return cases
- else
- call s:nextToken()
- call s:SyntaxError('case.default.rbrace.expected')
- endif
- endwhile
-endfu
-
-" MoreStatementExpressions = { COMMA StatementExpression }
-fu! s:moreStatementExpressions(pos, first, stats)
- call add(a:stats, {'tag': 'EXEC', 'pos': a:pos, 'expr': s:checkExprStat(a:first)})
- while b:token == 'COMMA'
- call s:nextToken()
- let pos = b:pos
- let t = s:expression()
- call add(a:stats, {'tag': 'EXEC', 'pos': pos, 'expr': s:checkExprStat(t)})
- endwhile
- return a:stats
-endfu
-
-" ForInit = StatementExpression MoreStatementExpressions
-" | { FINAL | '@' Annotation } Type VariableDeclarators
-fu! s:forInit()
- let stats = []
- let pos = b:pos
- if b:token == 'FINAL' || b:token == 'MONKEYS_AT'
- return s:variableDeclarators(s:optFinal(0), s:type(), stats)
- else
- let t = s:term(s:EXPR_OR_TYPE)
- if s:BitAnd(b:lastmode, s:TYPE) && b:token =~# '^\(IDENTIFIER\|ASSERT\|ENUM\)$'
- return s:variableDeclarators(s:modifiersOpt(), t, stats)
- else
- return s:moreStatementExpressions(pos, t, stats)
- endif
- endif
-endfu
-
-" ForUpdate = StatementExpression MoreStatementExpressions
-fu! s:forUpdate()
- return s:moreStatementExpressions(b:pos, s:expression(), [])
-endfu
-
-" ModifiersOpt = { Modifier } {{{2
-" Modifier = PUBLIC | PROTECTED | PRIVATE | STATIC | ABSTRACT | FINAL
-" | NATIVE | SYNCHRONIZED | TRANSIENT | VOLATILE | "@"
-" | "@" Annotation
-" NOTE: flags is a string, not a long number
-fu! s:modifiersOpt(...)
- let partial = a:0 == 0 ? {} : a:1
-
- let flags = partial == {} ? 0 : partial.flags
- let annotations = partial == {} ? [] : partial.annotations
- " TODO: deprecatedFlag
-
- let pos = b:pos
- let lastPos = -1
- while 1
- let flag = 0
- if b:token =~# '^\(PUBLIC\|PROTECTED\|PRIVATE\|STATIC\|ABSTRACT\|FINAL\|NATIVE\|SYNCHRONIZED\|TRANSIENT\|VOLATILE\|STRICTFP\|MONKEYS_AT\)$'
- let flag = b:token == 'MONKEYS_AT' ? s:Flags.ANNOTATION : get(s:Flags, b:token, 0)
- else
- break
- endif
- "if s:BitAnd(flags, flag) != 0
- " "log.error(S.pos(), "repeated.modifier")
- "endif
-
- let lastPos = b:pos
- call s:nextToken()
-
- if flag == s:Flags.ANNOTATION
- "call s:checkAnnotations()
- if b:token != 'INTERFACE'
- let ann = s:annotation(lastPos)
- if flags == 0 && annotations == []
- let pos = ann.pos
- endif
- call add(annotations, ann)
- let lastPos = ann.pos
- let flag = 0
- endif
- endif
- let flags = s:BitOr(flags, flag)
- endwhile
-
- if b:token == 'ENUM'
- let flags = s:BitOr(flags, s:Flags.ENUM)
- elseif b:token == 'INTERFACE'
- let flags = s:BitOr(flags, s:Flags.INTERFACE)
- endif
-
- if flags == 0 && empty(annotations)
- let pos = -1
- endif
-
- return {'tag': 'MODIFIERS', 'pos': pos, 'flags': flags, 'annotations': annotations}
-endfu
-
-" Annotation = "@" Qualident [ "(" AnnotationFieldValues ")" ] {{{2
-fu! s:annotation(pos)
- "call s:checkAnnotations()
- let ident = s:qualident()
- "let endPos = b:prevEndPos
- let fieldValues = s:annotationFieldValuesOpt()
-
- return {'tag': 'ANNOTATION', 'pos': a:pos, 'annotationType': ident, 'args': fieldValues}
-endfu
-
-fu! s:annotationFieldValuesOpt()
- return b:token == 'LPAREN' ? s:annotationFieldValues() : []
-endfu
-
-" AnnotationFieldValues = "(" [ AnnotationFieldValue { "," AnnotationFieldValue } ] ")"
-fu! s:annotationFieldValues()
- let buf = []
- call s:accept('LPAREN')
- if b:token != 'RPAREN'
- call add(buf, s:annotationFieldValue())
- while b:token == 'COMMA'
- call s:nextToken()
- call add(buf, s:annotationFieldValue())
- endwhile
- endif
- call s:accept('RPAREN')
- return buf
-endfu
-
-" AnnotationFieldValue = AnnotationValue | Identifier "=" AnnotationValue
-fu! s:annotationFieldValue()
- call s:Trace('s:annotationFieldValue ' . b:token)
- if b:token == 'IDENTIFIER'
- let b:mode = s:EXPR
- let t1 = s:term1()
- if t1.tag == 'IDENT' && b:token == 'EQ'
- let pos = b:pos
- call s:accept('EQ')
- return {'tag': 'ASSIGN', 'pos': pos, 'lhs': t1, 'rhs': s:annotationValue()}
- else
- return t1
- endif
- endif
- return s:annotationValue()
-endfu
-
-" AnnotationValue = ConditionalExpression | Annotation | "{" [ AnnotationValue { "," AnnotationValue } ] "}"
-fu! s:annotationValue()
- let pos = 0
- if b:token == 'MONKEYS_AT'
- let pos = b:bp
- call s:nextToken()
- return s:annotation(pos)
- elseif b:token == 'LBRACE'
- let pos = b:pos
- call s:accept('LBRACE')
- let buf = []
- if b:token != 'RBRACE'
- call add(buf, s:annotationValue())
- while b:token == 'COMMA'
- call s:nextToken()
- if b:token == 'RPAREN'
- break
- endif
- call add(buf, s:annotationValue())
- endwhile
- endif
- call s:accept('RBRACE')
- return buf
- else
- let b:mode = s:EXPR
- return s:term1()
- endif
-endfu
-
-" AnnotationsOpt = { '@' Annotation }
-fu! s:annotationsOpt()
- if b:token != 'MONKEYS_AT'
- return []
- endif
-
- let buf = []
- while b:token != 'MONKEYS_AT'
- let pos = b:pos
- call s:nextToken()
- call add(buf, s:annotation(pos))
- endwhile
- return buf
-endfu
-
-" {{{2
-" CompilationUnit {{{2
-" CompilationUnit = [ { "@" Annotation } PACKAGE Qualident ";"] {ImportDeclaration} {TypeDeclaration}
-fu! s:compilationUnit()
- let unit = {'tag': 'TOPLEVEL', 'pos': b:pos}
-
- let mods = {}
- if b:token == 'MONKEYS_AT'
- let mods = s:modifiersOpt()
- endif
-
- if b:token == 'PACKAGE'
- if mods != {}
- " checkNoMods(mods.flags)
- let unit.packageAnnotations = mods.annotations
- let mods = {}
- endif
- call s:nextToken()
- let unit.pid = s:qualident()
- let unit.package = java_parser#type2Str(unit.pid)
- call s:accept('SEMI')
- endif
-
- let imports = []
- let s:types = []
- let checkForImports = 1
- while b:token != 'EOF'
- if b:pos <= b:errorEndPos
- call s:skip(checkForImports, 0, 0, 0)
- if b:token == 'EOF'
- break
- endif
- endif
- if checkForImports && mods == {} && b:token == 'IMPORT'
- call add(imports, s:importDeclaration())
- else
- let def = s:typeDeclaration(mods)
- "if (def instanceof JCExpressionStatement)
- " def = ((JCExpressionStatement)def).expr
- "endif
- call add(s:types, def)
- if def.tag == 'CLASSDEF'
- let checkForImports = 0
- endif
- let mods = {}
- endif
- endwhile
- let unit.imports = imports
- let unit.types = s:types
- unlet s:types
-
- return unit
-endfu
-
-" ImportDeclaration = IMPORT [ STATIC ] Ident { "." Ident } [ "." "*" ] ";" {{{2
-" return fqn
-fu! s:importDeclaration()
- " OAO: Usualy it is in one line.
- if b:scanStrategy < 0
- let idx = matchend(b:lines[b:line], '\(\s\+static\>\)\?\s\+\([_$a-zA-Z][_$a-zA-Z0-9_]*\)\(\s*\.\s*[_$a-zA-Z][_$a-zA-Z0-9_]*\)*\(\s*\.\s*\*\)\?;')
- if idx != -1
- let fqn = strpart(b:lines[b:line], b:col, idx-b:col-1)
- let b:col = idx
- let b:bp = b:idxes[b:line] + b:col
- call s:nextToken()
- return fqn
- endif
- endif
-
-
- call s:Info('==import==')
- let pos = b:pos
- call s:nextToken()
-
- let importStatic = 0
- if b:token == 'STATIC'
- " checkStaticImports()
- let importStatic = 1
- call s:nextToken()
- endif
-
- let pid = s:Ident(b:pos, s:ident())
-
- "
- let pos1 = b:pos
- call s:accept('DOT')
- if b:token == 'STAR'
- let pid = s:Select(pos1, pid, '*')
- call s:nextToken()
- else
- let pid = s:Select(pos1, pid, s:ident())
- endif
- while b:token == 'DOT'
- let pos1 = b:pos
- call s:accept('DOT')
- if b:token == 'STAR'
- let pid = s:Select(pos1, pid, '*')
- call s:nextToken()
- break
- else
- let pid = s:Select(pos1, pid, s:ident())
- endif
- endwhile
- let fqn = java_parser#type2Str(pid)
- if b:token != 'SEMI'
- let fqn .= '<SEMI expected>'
- endif
- call s:accept('SEMI')
- "return {'tag': 'IMPORT', 'pos': b:pos, 'qualid': pid, 'staticImport': importStatic}
- return fqn
-endfu
-
-" TypeDeclaration = ClassOrInterfaceOrEnumDeclaration | ";" {{{2
-fu! s:typeDeclaration(mods)
- let pos = b:pos
- if a:mods == {} && b:token == 'SEMI'
- call s:nextToken()
- return {'tag': 'SKIP', 'pos': pos}
- else
- let dc = b:docComment
- let mods = s:modifiersOpt(a:mods)
- return s:classOrInterfaceOrEnumDeclaration(mods, dc)
- endif
-endfu
-
-fu! s:classOrInterfaceOrEnumDeclaration(mods, dc)
- call s:Info('== type ==')
- if b:token == 'CLASS'
- return s:classDeclaration(a:mods, a:dc)
- elseif b:token == 'INTERFACE'
- return s:interfaceDeclaration(a:mods, a:dc)
- elseif b:token == 'ENUM'
- "if !exists('b:allowEnums') || !b:allowEnums
- " call s:SyntaxError("enums.not.supported.in.source")
- "endif
- return s:enumDeclaration(a:mods, a:dc)
- else
- let pos = b:pos
- let errs = []
- if b:token == 'IDENTIFIER'
- call add(errs, s:ident())
- call s:setErrorEndPos(b:bp)
- endif
- return s:SyntaxError("class.or.intf.or.enum.expected", pos, errs)
- endif
-endfu
-
-" ClassDeclaration = CLASS Ident TypeParametersOpt [EXTENDS Type] [IMPLEMENTS TypeList] ClassBody {{{2
-fu! s:classDeclaration(mods, dc)
- let type = s:ClassDef(b:pos, a:mods)
-
- call s:accept('CLASS')
- let type.name = s:ident()
-
- let type.typarams = s:typeParametersOpt()
-
- " extends
- if b:token == 'EXTENDS'
- call s:nextToken()
- let type.extends = [s:type()]
- endif
-
- " implements
- if b:token == 'IMPLEMENTS'
- call s:nextToken()
- let type.implements = s:typeList()
- endif
-
- let type.defs = s:classOrInterfaceBody(type.name, 0)
- let type.endpos = b:pos
- return type
-endfu
-
-" InterfaceDeclaration = INTERFACE Ident TypeParametersOpt [EXTENDS TypeList] InterfaceBody {{{2
-fu! s:interfaceDeclaration(mods, dc)
- let type = s:ClassDef(b:pos, a:mods)
-
- call s:accept('INTERFACE')
- let type.name = s:ident()
-
- let type.typarams = s:typeParametersOpt()
-
- " extends
- if b:token == 'EXTENDS'
- call s:nextToken()
- let type.extends = s:typeList()
- endif
-
- let type.defs = s:classOrInterfaceBody(type.name, 1)
- let type.endpos = b:pos
- return type
-endfu
-
-" EnumDeclaration = ENUM Ident [IMPLEMENTS TypeList] EnumBody {{{2
-fu! s:enumDeclaration(mods, dc)
- let type = s:ClassDef(b:pos, a:mods)
-
- call s:accept('ENUM')
- let type.name = s:ident()
-
- if b:token == 'IMPLEMENTS'
- call s:nextToken()
- let type.implements = s:typeList()
- endif
-
- let type.defs = s:enumBody(type.name)
- let type.endpos = b:pos
- return type
-endfu
-
-" EnumBody = "{" { EnumeratorDeclarationList } [","]
-" [ ";" {ClassBodyDeclaration} ] "}"
-fu! s:enumBody(enumName)
- let defs = []
- call s:accept('LBRACE')
-
- if b:token == 'COMMA'
- call s:nextToken()
- elseif b:token != 'RBRACE' && b:token != 'SEMI'
- call add(defs, s:enumeratorDeclaration(a:enumName))
- while b:token == 'COMMA'
- call s:nextToken()
- if b:token == 'RBRACE' || b:token == 'SEMI'
- break
- endif
- call add(defs, s:enumeratorDeclaration(a:enumName))
- endwhile
- if b:token != 'RBRACE' && b:token != 'SEMI'
- call s:SyntaxError('comma.or.rbrace.or.semi. expected')
- call s:nextToken()
- endif
- endif
-
- if b:token == 'SEMI'
- call s:nextToken()
- while b:token != 'RBRACE' && b:token != 'EOF'
- call add(defs, s:classOrInterfaceBodyDeclaration(a:enumName, 0))
- if b:pos <= b:errorEndPos
- call s:skip(0, 1, 1, 0)
- endif
- endwhile
- endif
-
- call s:accept('RBRACE')
- return defs
-endfu
-
-" EnumeratorDeclaration = AnnotationsOpt [TypeArguments] IDENTIFIER [ Arguments ] [ "{" ClassBody "}" ]
-fu! s:enumeratorDeclaration(enumName)
- let vardef = {'tag': 'VARDEF', 'pos': b:pos}
-
- let dc = b:docComment
- let flags = 16409 " s:BitOr(s:Flags.PUBLIC, s:Flags.STATIC, s:Flags.FINAL, s:Flags.ENUM)
- " if b:deprecatedFlag
- " let flags = 147481 " s:BitOr(flags, s:Flags.DEPRECATED)
- " let b:deprecatedFlag = 1
- " endif
- let pos = b:pos
- let annotations = s:annotationsOpt()
- let vardef.mods = s:Modifiers(pos, flags, annotations)
- let vardef.mods.pos = empty(annotations) ? -1 : pos
- let vardef.m = s:Number2Bits(flags)
-
- let typeArgs = s:typeArgumentsOpt()
- let identPos = b:pos
- let vardef.name = s:ident()
- let vardef.n = vardef.name
-
- let args = b:token == 'LPAREN' ? s:arguments() : []
-
- " NOTE: It may be either a class body or a method body. I dont care, just record it
- if b:token == 'LBRACE'
- "call s:accept('LBRACE')
- "if b:token !=# 'RBRACE'
- " call s:gotoMatchEnd('{', '}')
- "endif
- "call s:accept('RBRACE')
-
- "let mods1 = s:Modifiers(-1, s:BitOr(s:Flags.ENUM, s:Flags.STATIC), [])
- let defs = s:classOrInterfaceBody('', 0)
- "let body = s:ClassDef(identPos, mods1)
- "let body.defs = defs
- endif
- let vardef.endpos = b:bp
-
- " TODO: create new class
-
- return vardef
-endfu
-
-" classOrInterfaceBody {{{2
-" ClassBody = "{" {ClassBodyDeclaration} "}"
-" InterfaceBody = "{" {InterfaceBodyDeclaration} "}"
-fu! s:classOrInterfaceBody(classname, isInterface)
- call s:Info('== type definition body ==')
- call s:accept('LBRACE')
-
- if b:pos <= b:errorEndPos
- call s:skip(0, 1, 0, 0)
- if b:token == 'LBRACE'
- call s:nextToken()
- endif
- endif
-
- let defs = []
- while b:token != 'RBRACE' && b:token != 'EOF'
- let defs += s:classOrInterfaceBodyDeclaration(a:classname, a:isInterface)
-
- if b:pos <= b:errorEndPos
- call s:skip(0, 1, 1, 0)
- endif
- endwhile
- call s:accept('RBRACE')
- return defs
-endfu
-
-" classOrInterfaceBodyDeclaration {{{2
-" ClassBodyDeclaration =
-" ";"
-" | [STATIC] Block
-" | ModifiersOpt
-" ( Type Ident
-" ( VariableDeclaratorsRest ";" | MethodDeclaratorRest )
-" | VOID Ident MethodDeclaratorRest
-" | TypeParameters (Type | VOID) Ident MethodDeclaratorRest
-" | Ident ConstructorDeclaratorRest
-" | TypeParameters Ident ConstructorDeclaratorRest
-" | ClassOrInterfaceOrEnumDeclaration
-" )
-" InterfaceBodyDeclaration =
-" ";"
-" | ModifiersOpt Type Ident
-" ( ConstantDeclaratorsRest | InterfaceMethodDeclaratorRest ";" )
-fu! s:classOrInterfaceBodyDeclaration(classname, isInterface)
- call s:Info('s:classOrInterfaceBodyDeclaration')
- if b:token == 'SEMI'
- call s:nextToken()
- return [{'tag': 'BLOCK', 'pos': -1, 'endpos': -1, 'stats': []}]
- else
- if b:scanStrategy < 0
- let result = s:classOrInterfaceBodyDeclaration_opt(a:classname, a:isInterface)
- if !empty(result)
- return result
- endif
- endif
-
-
- let dc = b:docComment
- let pos = b:bp
- let mods = s:modifiersOpt()
-
- if b:token =~# '^\(CLASS\|INTERFACE\|ENUM\)$'
- return [s:classOrInterfaceOrEnumDeclaration(mods, dc)]
-
- " [STATIC] block
- elseif b:token == 'LBRACE' && !a:isInterface
- return [s:block(pos, mods.flags, b:scanStrategy < 1)]
-
- else
- let typarams = s:typeParametersOpt()
-
- let token = b:token
- let name = b:name
-
- let type = copy(s:TTree)
- let isVoid = b:token == 'VOID'
- if isVoid
- let type = {'tag': 'TYPEIDENT', 'pos': pos, 'typetag': 'void'} " FIXME
- let type.value = ''
- call s:nextToken()
- else
- let time = reltime()
- let type = s:type()
- let b:et_perf .= "\r" . reltimestr(reltime(time)) . ' s:type() '
- endif
-
-
- " ctor
- if b:token == 'LPAREN' && !a:isInterface && type.tag == 'IDENT'
- if a:isInterface || name != a:classname
- call s:SyntaxError('invalid.meth.decl.ret.type.req')
- endif
- return [s:methodDeclaratorRest(pos, mods, type, name, typarams, a:isInterface, 1, dc)]
- else
- let name = s:ident()
- " method
- if b:token == 'LPAREN'
- return [s:methodDeclaratorRest(pos, mods, type, name, typarams, a:isInterface, isVoid, dc)]
- " field
- elseif !isVoid && len(typarams) == 0
- let defs = s:variableDeclaratorsRest(pos, mods, type, name, a:isInterface, dc, copy([]))
- call s:accept('SEMI')
- return defs
- else
- call s:SyntaxError("LPAREN expected")
- return [{}]
- endif
- endif
- endif
- endif
-endfu
-
-" OAO: short way for common declaration of field or method, not for generic type yet.
-fu! s:classOrInterfaceBodyDeclaration_opt(classname, isInterface)
- let str = b:lines[b:line]
- let idx = matchend(str, s:RE_MEMBER_HEADER)
- if idx != -1
- let subs = split(substitute(strpart(str, 0, idx), s:RE_MEMBER_HEADER, '\1;\2;\3', ''), ';')
- let name_ = subs[2]
- let type_ = subs[1]
- let flag_ = s:String2Flags(subs[0])
-
-" if type_ =~# '^\(class\|interface\|enum\)$'
-" return [s:classOrInterfaceOrEnumDeclaration(mods, dc)]
-" else
- " methodDeclarator
- let idx = matchend(str, '^\s*[,=;(]', idx)-1
- if str[idx] == '('
- let methoddef = s:methodDeclaratorRest_opt(b:pos, flag_, type_, name_, [], a:isInterface, type_ == 'void', '', str, idx)
- if !empty(methoddef)
- return [methoddef]
- endif
-
- " variableDeclarator
- elseif str[idx] =~ '[=;]'
- let vardef = {'tag': 'VARDEF', 'pos': b:pos, 'name': name_, 'n': name_, 'vartype': type_, 't': type_, 'm': flag_}
- call s:gotoSemi()
- call s:accept('SEMI')
- let vardef.pos_end = b:pos
- return [vardef]
-
- " variableDeclarators
- elseif str[idx] == ','
- let ie = matchend(str, '^\(,\s*'. s:RE_IDENTIFIER .'\s*\)*;', idx)
- if ie != -1
- let vardef = {'tag': 'VARDEF', 'pos': b:pos, 'name': name_, 'n': name_, 'vartype': type_, 't': type_, 'm': flag_}
- let vars = [vardef]
- for item in split(substitute(strpart(str, idx+1, ie-idx-2), '\s', '', 'g'), ',')
- let vardef = copy(vardef)
- let vardef.name = item
- let vardef.n = item
- call add(vars, vardef)
- endfor
- let b:col = ie
- let b:bp = b:idxes[b:line] + b:col
- call s:nextToken()
- return vars
- endif
- endif
-" endif
- endif
-
- let RE_CTOR_HEADER = '^\s*\(\(public\|protected\|private\)\s\+\)\=\C' .a:classname. '\s*('
- let ie = matchend(str, RE_CTOR_HEADER)
- if ie != -1 && !a:isInterface
- let flag_ = s:String2Flags(substitute(strpart(str, 0, ie), RE_CTOR_HEADER, '\1', ''))
- let methoddef = s:methodDeclaratorRest_opt(b:pos, flag_, a:classname, a:classname, [], a:isInterface, 1, '', str, ie-1)
- if !empty(methoddef)
- return [methoddef]
- endif
- endif
-
- let RE_METHOD_HEADER = '^\s*\(' .s:RE_IDENTIFIER. '\%(\s*\.\s*' .s:RE_IDENTIFIER. '\)*\%(\s*\[\s*\]\)\=\)\s\+\(' .s:RE_IDENTIFIER. '\)\s*('
- let ie = matchend(str, RE_METHOD_HEADER)
- if ie != -1
- let subs = split(substitute(strpart(str, 0, ie), RE_METHOD_HEADER, '\1;\2', ''), ';')
- let methoddef = s:methodDeclaratorRest_opt(b:pos, 0, subs[0], subs[1], [], a:isInterface, subs[0] == 'void', '', str, ie-1)
- if !empty(methoddef)
- return [methoddef]
- endif
- endif
-endfu
-
-
-" MethodDeclaratorRest = {{{2
-" FormalParameters BracketsOpt [Throws TypeList] ( MethodBody | [DEFAULT AnnotationValue] ";")
-" VoidMethodDeclaratorRest = FormalParameters [Throws TypeList] ( MethodBody | ";")
-" InterfaceMethodDeclaratorRest = FormalParameters BracketsOpt [THROWS TypeList] ";"
-" VoidInterfaceMethodDeclaratorRest = FormalParameters [THROWS TypeList] ";"
-" ConstructorDeclaratorRest = "(" FormalParameterListOpt ")" [THROWS TypeList] MethodBody
-fu! s:methodDeclaratorRest(pos, mods, type, name, typarams, isInterface, isVoid, dc)
- let time = reltime()
- let methoddef = {'tag': 'METHODDEF', 'pos': a:pos, 'name': a:name, 'mods': a:mods, 'restype': a:type, 'typarams': a:typarams}
- let methoddef.n = a:name
- let methoddef.m = s:Number2Bits(a:mods.flags)
- let methoddef.r = java_parser#type2Str(a:type)
-
- " parameters
- let methoddef.params = s:formalParameters()
-
- " BracketsOpt
- if !a:isVoid
- let methoddef.r = java_parser#type2Str(s:bracketsOpt(a:type))
- endif
-
-
- " throws
- if b:token == 'THROWS'
- call s:nextToken()
-
- " thrown = qualidentList()
- let ts = [s:qualident()]
- while b:token == 'COMMA'
- call s:nextToken()
- call add(ts, s:qualident())
- endwhile
- let methoddef.throws = ts
- endif
-
- " method body
- if b:token == 'LBRACE'
- let methoddef.body = s:block(b:pos, 0, b:scanStrategy < 1)
- else
- if b:token == 'DEFAULT'
- call s:accept('DEFAULT')
- let methoddef.defaultValue = s:annotationValue()
- endif
- call s:accept('SEMI')
-
- if b:pos <= b:errorEndPos
- call s:skip(0, 1, 0, 0)
- if b:token == 'LBRACE'
- let methoddef.body = s:block(b:pos, 0, b:scanStrategy < 1)
- endif
- endif
- endif
-
- let methoddef.d = s:method2Str(methoddef)
- let b:et_perf .= "\r" . reltimestr(reltime(time)) . ' methodrest() '
- return methoddef
-endfu
-
-" method header declared in one line,
-" NOTE: RE_FORMAL_PARAM_LIST do not recognize varargs and nested comments
-fu! s:methodDeclaratorRest_opt(pos, mods, type, name, typarams, isInterface, isVoid, dc, str, idx)
- let str = a:str
- let idx = a:idx
-
- " params
- let idxend = matchend(str, '^(\s*)', idx) " no params
- if idxend == -1
- let idxend = matchend(str, '^(\s*' . s:RE_FORMAL_PARAM_LIST . '\s*)', idx)
- endif
- if idxend == -1
- return
- endif
-
- let methoddef = {'tag': 'METHODDEF', 'pos': a:pos, 'name': a:name, 'n': a:name, 'm': a:mods, 'r': a:type}
-
- " params
- let methoddef.params = []
- let s = strpart(str, idx+1, idxend-idx-2)
- if s !~ '^\s*$'
- for item in split(s, ',')
- let subs = split(substitute(item, s:RE_FORMAL_PARAM2, '\2;\5', ''), ';')
- let param = {'tag': 'VARDEF', 'pos': -1}
- let param.name = subs[1]
- let param.vartype = substitute(subs[0], ' ', '', 'g')
- let param.m = s:Flags.PARAMETER
- call add(methoddef.params, param)
- endfor
- endif
-
- " throws
- let idx2 = matchend(str, '^\s*' . s:RE_THROWS, idxend)
- let idx = idx2 == -1 ? idxend : idx2
- if idx2 != -1
- "let throws = strpart(str, idxend, idx-idxend)
- endif
-
- " in interface
- if a:isInterface
- let idx = matchend(str, '^\s*;', idx)
- if idx != -1
- let b:token = 'SEMI'
- let b:col = idx
- let b:bp = b:idxes[b:line] + b:col
- let b:pos = b:bp - 1
- let methoddef.d = substitute(str, '^\s*\([^{]*\)\s*;\=$', '\1', '')
- return methoddef
- endif
- endif
-
- let idx = matchend(str, '^\s*{', idx)
- if idx == -1
- let idx = matchend(b:lines[b:line+1], '^\s*{')
- if idx != -1
- let b:line += 1
- endif
- endif
- if idx != -1
- let b:token = 'LBRACE'
- let b:col = idx
- let b:bp = b:idxes[b:line] + b:col
- let b:pos = b:bp - 1
- let methoddef.d = substitute(str, '^\s*\([^{]*\)\s*{\=$', '\1', '')
- let methoddef.body = s:block(b:pos, 0, b:scanStrategy < 1)
- return methoddef
- endif
-endfu
-
-" VariableDeclarators = VariableDeclarator { "," VariableDeclarator } {{{2
-fu! s:variableDeclarators(mods, type, vdefs)
- return s:variableDeclaratorsRest(b:pos, a:mods, a:type, s:ident(), 0, '', a:vdefs)
-endfu
-
-" VariableDeclaratorsRest = VariableDeclaratorRest { "," VariableDeclarator }
-" ConstantDeclaratorsRest = ConstantDeclaratorRest { "," ConstantDeclarator }
-fu! s:variableDeclaratorsRest(pos, mods, type, name, reqInit, dc, vdefs)
- call add(a:vdefs, s:variableDeclaratorRest(a:pos, a:mods, a:type, a:name, a:reqInit, a:dc))
- while b:token == 'COMMA'
- call s:nextToken()
- call add(a:vdefs, s:variableDeclarator(a:mods, a:type, a:reqInit, a:dc))
- endwhile
- return a:vdefs
-endfu
-
-" VariableDeclarator = Ident VariableDeclaratorRest
-" ConstantDeclarator = Ident ConstantDeclaratorRest
-fu! s:variableDeclarator(mods, type, reqInit, dc)
- return s:variableDeclaratorRest(b:pos, a:mods, a:type, s:ident(), a:reqInit, a:dc)
-endfu
-
-" VariableDeclaratorRest = BracketsOpt ["=" VariableInitializer]
-" ConstantDeclaratorRest = BracketsOpt "=" VariableInitializer
-fu! s:variableDeclaratorRest(pos, mods, type, name, reqInit, dc)
- let vardef = s:VarDef(a:pos, a:mods, a:name, s:bracketsOpt(a:type))
- let vardef.n = vardef.name
- let vardef.m = a:mods == {} ? '0' : s:Number2Bits(a:mods.flags)
- let vardef.t = java_parser#type2Str(vardef.vartype)
-
- if b:token == 'EQ'
- call s:nextToken()
- call s:Info('field init ' . b:token)
- let vardef.init = s:variableInitializer()
- elseif a:reqInit
- echo '[syntax error]:' . s:token2string('EQ') . " expected"
- endif
-
- let vardef.endpos = b:pos
- return vardef
-endfu
-
-fu! s:variableDeclaratorId(mods, type)
- let vardef = s:VarDef(b:pos, a:mods, s:ident(), a:type)
- if len(a:mods.flags) <= 34 " (a:mods.flags & s:Flags.VARARGS) == 0
- let vardef.type = s:bracketsOpt(vardef.vartype)
- endif
- return vardef
-endfu
-
-" {{{2
-" TypeParametersOpt = ["<" TypeParameter {"," TypeParameter} ">"] {{{2
-fu! s:typeParametersOpt()
- if b:token == 'LT'
- "call checkGenerics()
- let typarams = []
- call s:nextToken()
- call add(typarams, s:typeParameter())
- while b:token == 'COMMA'
- call s:nextToken()
- call add(typarams, s:typeParameter())
- endwhile
- call s:accept('GT')
- return typarams
- else
- return []
- endif
-endfu
-
-" TypeParameter = TypeVariable [TypeParameterBound] {{{2
-" TypeParameterBound = EXTENDS Type {"&" Type}
-" TypeVariable = Ident
-fu! s:typeParameter()
- let pos = b:pos
- let name = s:ident()
- let bounds = []
- if b:token == 'EXTENDS'
- call s:nextToken()
- call add(bounds, s:type())
- while b:token == 'AMP'
- call s:nextToken()
- call add(bounds, s:type())
- endwhile
- endif
-
- return {'tag': 'TYPEPARAMETER', 'pos': pos, 'name': name, 'bounds': bounds}
-endfu
-
-" FormalParameters = "(" [ FormalParameterList ] ")" {{{2
-" FormalParameterList = [ FormalParameterListNovarargs , ] LastFormalParameter
-" FormalParameterListNovarargs = [ FormalParameterListNovarargs , ] FormalParameter
-fu! s:formalParameters()
- let params = []
- let lastParam = {}
- call s:accept('LPAREN')
- if b:token != 'RPAREN'
- let lastParam = s:formalParameter()
- call add(params, lastParam)
- while b:token == 'COMMA' && len(lastParam.mods.flags) <= 34 " (lastParam.mods.flags & s:Flags.VARARGS) == 0
- call s:nextToken()
- let lastParam = s:formalParameter()
- call add(params, lastParam)
- endwhile
- endif
- call s:accept('RPAREN')
- return params
-endfu
-
-" FormalParameter = { FINAL | '@' Annotation } Type VariableDeclaratorId {{{2
-" LastFormalParameter = { FINAL | '@' Annotation } Type '...' Ident | FormalParameter
-fu! s:optFinal(flags)
- let mods = s:modifiersOpt()
- " checkNoMods(mods.flags & ~(Flags.FINAL | Flags.DEPRECATED))
- let mods.flags = s:BitOr(mods.flags, a:flags)
- return mods
-endfu
-
-" OAO: optional FINAL for parameter
-fu! s:optFinalParameter()
- let mods = {'tag': 'MODIFIERS', 'pos': b:pos, 'flags': s:Flags.PARAMETER, 'annotations': []}
- if b:token == 'FINAL'
- let mods.flags = '1000000000000000000000000000010000'
- call s:nextToken()
- endif
- return mods
-endfu
-
-fu! s:formalParameter()
- let mods = s:optFinalParameter()
- let type = s:type()
-
- if b:token == 'ELLIPSIS'
- " checkVarargs()
- let mods.flags = '1' . mods.flags " s:BitOr_binary(mods.flags, s:Flags.VARARGS)
- let type = s:TypeArray(b:pos, type)
- call s:nextToken()
- endif
-
- return s:variableDeclaratorId(mods, type)
-endfu
-
-" {{{2
-" auxiliary methods {{{2
-let s:MapToken2Tag = {'BARBAR': 'OR', 'AMPAMP': 'AND', 'BAR': 'BITOR', 'BAREQ': 'BITOR_ASG', 'CARET': 'BITXOR', 'CARETEQ': 'BITXOR_ASG', 'AMP': 'BITAND', 'AMPEQ': 'BITAND_ASG', 'EQEQ': 'EQ', 'BANGEQ': 'NE', 'LT': 'LT', 'GT': 'GT', 'LTEQ': 'LE', 'GTEQ': 'GE', 'LTLT': 'SL', 'LTLTEQ': 'SL_ASG', 'GTGT': 'SR', 'GTGTEQ': 'SR_ASG', 'GTGTGT': 'USR', 'GTGTGTEQ': 'USR_ASG', 'PLUS': 'PLUS', 'PLUSEQ': 'PLUS_ASG', 'SUB': 'MINUS', 'SUBEQ': 'MINUS_ASG', 'STAR': 'MUL', 'STAREQ': 'MUL_ASG', 'SLASH': 'DIV', 'SLASHEQ': 'DIV_ASG', 'PERCENT': 'MOD', 'PERCENTEQ': 'MOD_ASG', 'INSTANCEOF': 'TYPETEST'}
-let s:opprecedences = {'notExpression': -1, 'noPrec': 0, 'assignPrec': 1, 'assignopPrec': 2, 'condPrec': 3, 'orPrec': 4, 'andPrec': 5, 'bitorPrec': 6, 'bitxorPrec': 7, 'bitandPrec': 8, 'eqPrec': 9, 'ordPrec': 10, 'shiftPrec': 11, 'addPrec': 12, 'mulPrec': 13, 'prefixPrec': 14, 'postfixPrec': 15, 'precCount': 16}
-
-fu! s:checkExprStat(t)
- if a:t.tag =~# '^\(PREINC\|PREDEC\|POSTINC\|POSTDEC\|ASSIGN\|BITOR_ASG\|BITXOR_ASG\|BITAND_ASG\|SL_ASG\|SR_ASG\|USR_ASG\|PLUS_ASG\|MINUS_ASG\|MUL_ASG\|DIV_ASG\|MOD_ASG\|APPLY\|NEWCLASS\|ERRONEOUS\)$'
- return a:t
- else
- call s:SyntaxError('not.stmt')
- return {'tag': 'ERRONEOUS', 'pos': b:pos, 'errs': [a:t]}
- endif
-endfu
-
-fu! s:prec(token)
- let oc = s:optag(a:token)
- return oc == -1 ? -1 : s:opPrec(oc)
-endfu
-
-fu! s:opPrec(tag)
- if a:tag =~# '^\(POS\|NEG\|NOT\|COMPL\|PREINC\|PREDEC\)$'
- return s:opprecedences.prefixPrec
- elseif a:tag =~# '^\(POSTINC\|POSTDEC\|NULLCHK\)$'
- return s:opprecedences.postfixPrec
- elseif a:tag == 'ASSIGN'
- return s:opprecedences.assignPrec
- elseif a:tag =~# '^\(BITOR_ASG\|BITXOR_ASG\|BITAND_ASG\|SL_ASG\|SR_ASG\|USR_ASG\|PLUS_ASG\|MINUS_ASG\|MUL_ASG\|DIV_ASG\|MOD_ASG\)$'
- return s:opprecedences.assignopPrec
- elseif a:tag == 'OR'
- return s:opprecedences.orPrec
- elseif a:tag == 'AND'
- return s:opprecedences.andPrec
- elseif a:tag =~# '^\(EQ\|NE\)$'
- return s:opprecedences.eqPrec
- elseif a:tag =~# '^\(LT\|GT\|LE\|GE\)$'
- return s:opprecedences.ordPrec
- elseif a:tag == 'BITOR'
- return s:opprecedences.bitorPrec
- elseif a:tag == 'BITXOR'
- return s:opprecedences.bitxorPrec
- elseif a:tag == 'BITAND'
- return s:opprecedences.bitandPrec
- elseif a:tag =~# '^\(SL\|SR\|USR\)$'
- return s:opprecedences.shiftPrec
- elseif a:tag =~# '^\(PLUS\|MINUS\)$'
- return s:opprecedences.addPrec
- elseif a:tag =~# '^\(MUL\|DIV\|MOD\)$'
- return s:opprecedences.mulPrec
- elseif a:tag == 'TYPETEST'
- return s:opprecedences.ordPrec
- else
- return -1
- endif
-endfu
-
-fu! s:optag(token)
- return get(s:MapToken2Tag, a:token, -1)
-endfu
-
-fu! s:unoptag(token)
- if a:token == 'PLUS'
- return 'POS'
- elseif a:token == 'SUB'
- return 'NEG'
- elseif a:token == 'BANG'
- return 'NOT'
- elseif a:token == 'TILDE'
- return 'COMPL'
- elseif a:token == 'PLUSPLUS'
- return 'PREINC'
- elseif a:token == 'SUBSUB'
- return 'PREDEC'
- else
- return -1
- endif
-endfu
-
-fu! s:typetag(token)
- if a:token =~# '\(BYTE\|CHAR\|SHORT\|INT\|LONG\|FLOAT\|DOUBLE\|BOOLEAN\)'
- return tolower(a:token)
- else
- return -1
- endif
-endfu
-
-"}}}1
-" vim:set fdm=marker sw=2 nowrap: