From bd0c5c655e30d54d0ecc5599c6c97a33300ac62d Mon Sep 17 00:00:00 2001 From: Zachary Yedidia Date: Sat, 25 Feb 2017 17:02:39 -0500 Subject: [PATCH] Add more syntax files and include syntax highlighter in the repo --- cmd/micro/buffer.go | 2 +- cmd/micro/highlight/ftdetect.go | 19 +++ cmd/micro/highlight/highlighter.go | 262 +++++++++++++++++++++++++++++ cmd/micro/highlight/parser.go | 202 ++++++++++++++++++++++ cmd/micro/highlighter.go | 2 +- cmd/micro/lineArray.go | 2 +- runtime/syntax/arduino.yaml | 98 +++++++++++ runtime/syntax/asm.yaml | 107 ++++++++++++ runtime/syntax/c.yaml | 6 +- runtime/syntax/caddyfile.yaml | 21 +++ runtime/syntax/coffeescript.yaml | 27 +++ runtime/syntax/dockerfile.yaml | 33 ++++ runtime/syntax/go.yaml | 2 +- runtime/syntax/syntax_checker.go | 30 ++++ 14 files changed, 807 insertions(+), 6 deletions(-) create mode 100644 cmd/micro/highlight/ftdetect.go create mode 100644 cmd/micro/highlight/highlighter.go create mode 100644 cmd/micro/highlight/parser.go create mode 100644 runtime/syntax/arduino.yaml create mode 100644 runtime/syntax/asm.yaml create mode 100644 runtime/syntax/caddyfile.yaml create mode 100644 runtime/syntax/coffeescript.yaml create mode 100644 runtime/syntax/dockerfile.yaml create mode 100644 runtime/syntax/syntax_checker.go diff --git a/cmd/micro/buffer.go b/cmd/micro/buffer.go index 4d31f3a0..1d054446 100644 --- a/cmd/micro/buffer.go +++ b/cmd/micro/buffer.go @@ -16,7 +16,7 @@ import ( "unicode/utf8" "github.com/mitchellh/go-homedir" - "github.com/zyedidia/highlight" + "github.com/zyedidia/micro/cmd/micro/highlight" ) // Buffer stores the text for files that are loaded into the text editor diff --git a/cmd/micro/highlight/ftdetect.go b/cmd/micro/highlight/ftdetect.go new file mode 100644 index 00000000..a0ac389f --- /dev/null +++ b/cmd/micro/highlight/ftdetect.go @@ -0,0 +1,19 @@ +package highlight + +func DetectFiletype(defs []*Def, filename string, firstLine []byte) *Def { + for _, d := range defs { + if d.ftdetect[0].Match([]byte(filename)) { + return d + } + if len(d.ftdetect) > 1 { + if d.ftdetect[1].Match(firstLine) { + return d + } + } + } + + emptyDef := new(Def) + emptyDef.FileType = "Unknown" + emptyDef.rules = new(Rules) + return emptyDef +} diff --git a/cmd/micro/highlight/highlighter.go b/cmd/micro/highlight/highlighter.go new file mode 100644 index 00000000..a60aa196 --- /dev/null +++ b/cmd/micro/highlight/highlighter.go @@ -0,0 +1,262 @@ +package highlight + +import ( + "regexp" + "strings" +) + +func combineLineMatch(src, dst LineMatch) LineMatch { + for k, v := range src { + if g, ok := dst[k]; ok { + if g == "" { + dst[k] = v + } + } else { + dst[k] = v + } + } + return dst +} + +type State *Region + +type LineStates interface { + LineData() [][]byte + State(lineN int) State + SetState(lineN int, s State) + SetMatch(lineN int, m LineMatch) +} + +type Highlighter struct { + lastRegion *Region + def *Def +} + +func NewHighlighter(def *Def) *Highlighter { + h := new(Highlighter) + h.def = def + return h +} + +type LineMatch map[int]string + +func FindIndex(regex *regexp.Regexp, str []byte, canMatchStart, canMatchEnd bool) []int { + regexStr := regex.String() + if strings.Contains(regexStr, "^") { + if !canMatchStart { + return nil + } + } + if strings.Contains(regexStr, "$") { + if !canMatchEnd { + return nil + } + } + return regex.FindIndex(str) +} + +func FindAllIndex(regex *regexp.Regexp, str []byte, canMatchStart, canMatchEnd bool) [][]int { + regexStr := regex.String() + if strings.Contains(regexStr, "^") { + if !canMatchStart { + return nil + } + } + if strings.Contains(regexStr, "$") { + if !canMatchEnd { + return nil + } + } + return regex.FindAllIndex(str, -1) +} + +func (h *Highlighter) highlightRegion(start int, canMatchEnd bool, lineNum int, line []byte, region *Region) LineMatch { + highlights := make(LineMatch) + + if len(line) == 0 { + if canMatchEnd { + h.lastRegion = region + } + + return highlights + } + + loc := FindIndex(region.end, line, start == 0, canMatchEnd) + if loc != nil { + if region.parent == nil { + highlights[start+loc[1]] = "" + return combineLineMatch(highlights, + combineLineMatch(h.highlightRegion(start, false, lineNum, line[:loc[0]], region), + h.highlightEmptyRegion(start+loc[1], canMatchEnd, lineNum, line[loc[1]:]))) + } + highlights[start+loc[1]] = region.parent.group + return combineLineMatch(highlights, + combineLineMatch(h.highlightRegion(start, false, lineNum, line[:loc[0]], region), + h.highlightRegion(start+loc[1], canMatchEnd, lineNum, line[loc[1]:], region.parent))) + } + + firstLoc := []int{len(line), 0} + var firstRegion *Region + for _, r := range region.rules.regions { + loc := FindIndex(r.start, line, start == 0, canMatchEnd) + if loc != nil { + if loc[0] < firstLoc[0] { + firstLoc = loc + firstRegion = r + } + } + } + if firstLoc[0] != len(line) { + highlights[start+firstLoc[0]] = firstRegion.group + return combineLineMatch(highlights, + combineLineMatch(h.highlightRegion(start, false, lineNum, line[:firstLoc[0]], region), + h.highlightRegion(start+firstLoc[1], canMatchEnd, lineNum, line[firstLoc[1]:], firstRegion))) + } + + for _, p := range region.rules.patterns { + matches := FindAllIndex(p.regex, line, start == 0, canMatchEnd) + for _, m := range matches { + highlights[start+m[0]] = p.group + if _, ok := highlights[start+m[1]]; !ok { + highlights[start+m[1]] = region.group + } + } + } + + if canMatchEnd { + h.lastRegion = region + } + + return highlights +} + +func (h *Highlighter) highlightEmptyRegion(start int, canMatchEnd bool, lineNum int, line []byte) LineMatch { + highlights := make(LineMatch) + if len(line) == 0 { + if canMatchEnd { + h.lastRegion = nil + } + return highlights + } + + firstLoc := []int{len(line), 0} + var firstRegion *Region + for _, r := range h.def.rules.regions { + loc := FindIndex(r.start, line, start == 0, canMatchEnd) + if loc != nil { + if loc[0] < firstLoc[0] { + firstLoc = loc + firstRegion = r + } + } + } + if firstLoc[0] != len(line) { + highlights[start+firstLoc[0]] = firstRegion.group + return combineLineMatch(highlights, + combineLineMatch(h.highlightEmptyRegion(start, false, lineNum, line[:firstLoc[0]]), + h.highlightRegion(start+firstLoc[1], canMatchEnd, lineNum, line[firstLoc[1]:], firstRegion))) + } + + for _, p := range h.def.rules.patterns { + matches := FindAllIndex(p.regex, line, start == 0, canMatchEnd) + for _, m := range matches { + highlights[start+m[0]] = p.group + if _, ok := highlights[start+m[1]]; !ok { + highlights[start+m[1]] = "" + } + } + } + + if canMatchEnd { + h.lastRegion = nil + } + + return highlights +} + +func (h *Highlighter) HighlightString(input string) []LineMatch { + lines := strings.Split(input, "\n") + var lineMatches []LineMatch + + for i := 0; i < len(lines); i++ { + line := []byte(lines[i]) + + if i == 0 || h.lastRegion == nil { + lineMatches = append(lineMatches, h.highlightEmptyRegion(0, true, i, line)) + } else { + lineMatches = append(lineMatches, h.highlightRegion(0, true, i, line, h.lastRegion)) + } + } + + return lineMatches +} + +func (h *Highlighter) Highlight(input LineStates, startline int) { + lines := input.LineData() + + for i := startline; i < len(lines); i++ { + line := []byte(lines[i]) + + var match LineMatch + if i == 0 || h.lastRegion == nil { + match = h.highlightEmptyRegion(0, true, i, line) + } else { + match = h.highlightRegion(0, true, i, line, h.lastRegion) + } + + curState := h.lastRegion + + input.SetMatch(i, match) + input.SetState(i, curState) + } +} + +func (h *Highlighter) ReHighlightLine(input LineStates, lineN int) { + lines := input.LineData() + + line := []byte(lines[lineN]) + + h.lastRegion = nil + if lineN > 0 { + h.lastRegion = input.State(lineN - 1) + } + + var match LineMatch + if lineN == 0 || h.lastRegion == nil { + match = h.highlightEmptyRegion(0, true, lineN, line) + } else { + match = h.highlightRegion(0, true, lineN, line, h.lastRegion) + } + curState := h.lastRegion + + input.SetMatch(lineN, match) + input.SetState(lineN, curState) +} + +func (h *Highlighter) ReHighlight(input LineStates, startline int) { + lines := input.LineData() + + h.lastRegion = nil + if startline > 0 { + h.lastRegion = input.State(startline - 1) + } + for i := startline; i < len(lines); i++ { + line := []byte(lines[i]) + + var match LineMatch + if i == 0 || h.lastRegion == nil { + match = h.highlightEmptyRegion(0, true, i, line) + } else { + match = h.highlightRegion(0, true, i, line, h.lastRegion) + } + curState := h.lastRegion + lastState := input.State(i) + + input.SetMatch(i, match) + input.SetState(i, curState) + + if curState == lastState { + break + } + } +} diff --git a/cmd/micro/highlight/parser.go b/cmd/micro/highlight/parser.go new file mode 100644 index 00000000..21a905fc --- /dev/null +++ b/cmd/micro/highlight/parser.go @@ -0,0 +1,202 @@ +package highlight + +import ( + "fmt" + "regexp" + + "gopkg.in/yaml.v2" +) + +// A Def is a full syntax definition for a language +// It has a filetype, information about how to detect the filetype based +// on filename or header (the first line of the file) +// Then it has the rules which define how to highlight the file +type Def struct { + FileType string + ftdetect []*regexp.Regexp + rules *Rules +} + +// A Pattern is one simple syntax rule +// It has a group that the rule belongs to, as well as +// the regular expression to match the pattern +type Pattern struct { + group string + regex *regexp.Regexp +} + +// Rules defines which patterns and regions can be used to highlight +// a filetype +type Rules struct { + regions []*Region + patterns []*Pattern + includes []string +} + +// A Region is a highlighted region (such as a multiline comment, or a string) +// It belongs to a group, and has start and end regular expressions +// A Region also has rules of its own that only apply when matching inside the +// region and also rules from the above region do not match inside this region +// Note that a region may contain more regions +type Region struct { + group string + parent *Region + start *regexp.Regexp + end *regexp.Regexp + rules *Rules +} + +// ParseDef parses an input syntax file into a highlight Def +func ParseDef(input []byte) (s *Def, err error) { + // This is just so if we have an error, we can exit cleanly and return the parse error to the user + defer func() { + if e := recover(); e != nil { + err = e.(error) + } + }() + + var rules map[interface{}]interface{} + if err = yaml.Unmarshal(input, &rules); err != nil { + return nil, err + } + + s = new(Def) + + for k, v := range rules { + if k == "filetype" { + filetype := v.(string) + + s.FileType = filetype + } else if k == "detect" { + ftdetect := v.(map[interface{}]interface{}) + if len(ftdetect) >= 1 { + syntax, err := regexp.Compile(ftdetect["filename"].(string)) + if err != nil { + return nil, err + } + + s.ftdetect = append(s.ftdetect, syntax) + } + if len(ftdetect) >= 2 { + header, err := regexp.Compile(ftdetect["header"].(string)) + if err != nil { + return nil, err + } + + s.ftdetect = append(s.ftdetect, header) + } + } else if k == "rules" { + inputRules := v.([]interface{}) + + rules, err := parseRules(inputRules, nil) + if err != nil { + return nil, err + } + + s.rules = rules + } + } + + return s, err +} + +func ResolveIncludes(defs []*Def) { + for _, d := range defs { + resolveIncludesInDef(defs, d) + } +} + +func resolveIncludesInDef(defs []*Def, d *Def) { + for _, lang := range d.rules.includes { + for _, searchDef := range defs { + if lang == searchDef.FileType { + d.rules.patterns = append(d.rules.patterns, searchDef.rules.patterns...) + d.rules.regions = append(d.rules.regions, searchDef.rules.regions...) + } + } + } + for _, r := range d.rules.regions { + resolveIncludesInRegion(defs, r) + r.parent = nil + } +} + +func resolveIncludesInRegion(defs []*Def, region *Region) { + for _, lang := range region.rules.includes { + for _, searchDef := range defs { + if lang == searchDef.FileType { + region.rules.patterns = append(region.rules.patterns, searchDef.rules.patterns...) + region.rules.regions = append(region.rules.regions, searchDef.rules.regions...) + } + } + } + for _, r := range region.rules.regions { + resolveIncludesInRegion(defs, r) + r.parent = region + } +} + +func parseRules(input []interface{}, curRegion *Region) (*Rules, error) { + rules := new(Rules) + + for _, v := range input { + rule := v.(map[interface{}]interface{}) + for k, val := range rule { + group := k + + switch object := val.(type) { + case string: + if k == "include" { + rules.includes = append(rules.includes, object) + } else { + // Pattern + r, err := regexp.Compile(object) + if err != nil { + return nil, err + } + + rules.patterns = append(rules.patterns, &Pattern{group.(string), r}) + } + case map[interface{}]interface{}: + // Region + region, err := parseRegion(group.(string), object, curRegion) + if err != nil { + return nil, err + } + rules.regions = append(rules.regions, region) + default: + return nil, fmt.Errorf("Bad type %T", object) + } + } + } + + return rules, nil +} + +func parseRegion(group string, regionInfo map[interface{}]interface{}, prevRegion *Region) (*Region, error) { + var err error + + region := new(Region) + region.group = group + region.parent = prevRegion + + region.start, err = regexp.Compile(regionInfo["start"].(string)) + + if err != nil { + return nil, err + } + + region.end, err = regexp.Compile(regionInfo["end"].(string)) + + if err != nil { + return nil, err + } + + region.rules, err = parseRules(regionInfo["rules"].([]interface{}), region) + + if err != nil { + return nil, err + } + + return region, nil +} diff --git a/cmd/micro/highlighter.go b/cmd/micro/highlighter.go index 5dd8a497..ba88a705 100644 --- a/cmd/micro/highlighter.go +++ b/cmd/micro/highlighter.go @@ -1,6 +1,6 @@ package main -import "github.com/zyedidia/highlight" +import "github.com/zyedidia/micro/cmd/micro/highlight" var syntaxDefs []*highlight.Def diff --git a/cmd/micro/lineArray.go b/cmd/micro/lineArray.go index 921e97db..30f16798 100644 --- a/cmd/micro/lineArray.go +++ b/cmd/micro/lineArray.go @@ -5,7 +5,7 @@ import ( "io" "unicode/utf8" - "github.com/zyedidia/highlight" + "github.com/zyedidia/micro/cmd/micro/highlight" ) func runeToByteIndex(n int, txt []byte) int { diff --git a/runtime/syntax/arduino.yaml b/runtime/syntax/arduino.yaml new file mode 100644 index 00000000..d5fc0b6c --- /dev/null +++ b/runtime/syntax/arduino.yaml @@ -0,0 +1,98 @@ +filetype: ino + +detect: + filename: "\\.?ino$" + +rules: + - identifier: "\\b[A-Z_][0-9A-Z_]+\\b" + + ## + - type: "\\b((s?size)|((u_?)?int(8|16|32|64|ptr)))_t\\b" + + ## Constants + - constant: "(?i)\\b(HIGH|LOW|INPUT|OUTPUT)\\b" + + ## Serial Print + - constant: "(?i)\\b(DEC|BIN|HEX|OCT|BYTE)\\b" + + ## PI Constants + - constant: "(?i)\\b(PI|HALF_PI|TWO_PI)\\b" + + ## ShiftOut + - constant: "(?i)\\b(LSBFIRST|MSBFIRST)\\b" + + ## Attach Interrupt + - constant: "(?i)\\b(CHANGE|FALLING|RISING)\\b" + + ## Analog Reference + - constant: "(?i)\\b(DEFAULT|EXTERNAL|INTERNAL|INTERNAL1V1|INTERNAL2V56)\\b" + + ## === FUNCTIONS === ## + + ## Data Types + - type: "\\b(boolean|byte|char|float|int|long|word)\\b" + + ## Control Structions + - statement: "\\b(case|class|default|do|double|else|false|for|if|new|null|private|protected|public|short|signed|static|String|switch|this|throw|try|true|unsigned|void|while)\\b" + - statement: "\\b(goto|continue|break|return)\\b" + + ## Math + - identifier: "\\b(abs|acos|asin|atan|atan2|ceil|constrain|cos|degrees|exp|floor|log|map|max|min|radians|random|randomSeed|round|sin|sq|sqrt|tan)\\b" + + ## Bits & Bytes + - identifier: "\\b(bitRead|bitWrite|bitSet|bitClear|bit|highByte|lowByte)\\b" + + ## Analog I/O + - identifier: "\\b(analogReference|analogRead|analogWrite)\\b" + + ## External Interrupts + - identifier: "\\b(attachInterrupt|detachInterrupt)\\b" + + ## Time + - identifier: "\\b(delay|delayMicroseconds|millis|micros)\\b" + + ## Digital I/O + - identifier: "\\b(pinMode|digitalWrite|digitalRead)\\b" + + ## Interrupts + - identifier: "\\b(interrupts|noInterrupts)\\b" + + ## Advanced I/O + - identifier: "\\b(noTone|pulseIn|shiftIn|shiftOut|tone)\\b" + + ## Serial + - identifier: "\\b(Serial|Serial1|Serial2|Serial3|begin|end|peek|read|print|println|available|flush)\\b" + + ## Structure + - identifier: "\\b(setup|loop)\\b" + + ## + - statement: "^[[:space:]]*#[[:space:]]*(define|include(_next)?|(un|ifn?)def|endif|el(if|se)|if|warning|error|pragma)" + + ## GCC builtins + - constant: "(__attribute__[[:space:]]*\\(\\([^)]*\\)\\)|__(aligned|asm|builtin|hidden|inline|packed|restrict|section|typeof|weak)__)" + + - constant.string: + start: "\"" + end: "\"" + rules: + - constant.specialChar: "\\\\." + + - constant.string: + start: "'" + end: "'" + rules: + - preproc: "..+" + - constant.specialChar: "\\\\." + + - comment: + start: "//" + end: "$" + rules: + - todo: "(TODO|XXX|FIXME):?" + + - comment: + start: "/\\*" + end: "\\*/" + rules: + - todo: "(TODO|XXX|FIXME):?" diff --git a/runtime/syntax/asm.yaml b/runtime/syntax/asm.yaml new file mode 100644 index 00000000..2752b6f3 --- /dev/null +++ b/runtime/syntax/asm.yaml @@ -0,0 +1,107 @@ +filetype: asm + +detect: + filename: "\\.(S|s|asm)$" + +rules: + # This file is made for NASM assembly + + ## Instructions + # x86 + - statement: "\\b(?i)(mov|aaa|aad|aam|aas|adc|add|and|call|cbw|clc|cld|cli|cmc|cmp|cmpsb|cmpsw|cwd|daa|das|dec|div|esc|hlt|idiv|imul|in|inc|int|into|iret|ja|jae|jb|jbe|jc|je|jg|jge|jl|jle|jna|jnae|jnb|jnbe|jnc|jne|jng|jnge|jnl|jnle|jno|jnp|jns|jnz|jo|jp|jpe|jpo|js|jz|jcxz|jmp|lahf|lds|lea|les|lock|lodsb|lodsw|loop|loope|loopne|loopnz|loopz|movsb|movsw|mul|neg|nop|or|pop|popf|push|pushf|rcl|rcr|rep|repe|repne|repnz|repz|ret|retn|retf|rol|ror|sahf|sal|sar|sbb|scasb|scasw|shl|shr|stc|std|sti|stosb|stosw|sub|test|wait|xchg|xlat|xor)(?-i)\\b" + - statement: "\\b(?i)(bound|enter|ins|leave|outs|popa|pusha)(?-i)\\b" + - statement: "\\b(?i)(arpl|clts|lar|lgdt|lidt|lldt|lmsw|loadall|lsl|ltr|sgdt|sidt|sldt|smsw|str|verr|verw)(?-i)\\b" + - statement: "\\b(?i)(bsf|bsr|bt|btc|btr|bts|cdq|cmpsd|cwde|insd|iret|iretd|iretf|jecxz|lfs|lgs|lss|lodsd|loopw|loopew|loopnew|loopnzw|loopzw|loopd|looped|loopned|loopnzd|loopzd|cr|tr|dr|movsd|movsx|movzx|outsd|popad|popfd|pushad|pushfd|scasd|seta|setae|setb|setbe|setc|sete|setg|setge|setl|setle|setna|setnae|setnb|setnbe|setnc|setne|setng|setnge|setnl|setnle|setno|setnp|setns|setnz|seto|setp|setpe|setpo|sets|setz|shdl|shrd|stosd)(?-i)\\b" + - statement: "\\b(?i)(bswap|cmpxcgh|invd|invlpg|wbinvd|xadd)(?-i)\\b" + - statement: "\\b(?i)(cpuid|cmpxchg8b|rdmsr|rdtsc|wrmsr|rsm)(?-i)\\b" + - statement: "\\b(?i)(rdpmc)(?-i)\\b" + - statement: "\\b(?i)(syscall|sysret)(?-i)\\b" + - statement: "\\b(?i)(cmova|cmovae|cmovb|cmovbe|cmovc|cmove|cmovg|cmovge|cmovl|cmovle|cmovna|cmovnae|cmovnb|cmovnbe|cmovnc|cmovne|cmovng|cmovnge|cmovnle|cmovno|cmovpn|cmovns|cmovnz|cmovo|cmovp|cmovpe|cmovpo|cmovs|cmovz|sysenter|sysexit|ud2)(?-i)\\b" + - statement: "\\b(?i)(maskmovq|movntps|movntq|prefetch0|prefetch1|prefetch2|prefetchnta|sfence)(?-i)\\b" + - statement: "\\b(?i)(clflush|lfence|maskmovdqu|mfence|movntdq|movnti|movntpd|pause)(?-i)\\b" + - statement: "\\b(?i)(monitor|mwait)(?-i)\\b" + - statement: "\\b(?i)(cdqe|cqo|cmpsq|cmpxchg16b|iretq|jrcxz|lodsq|movsdx|popfq|pushfq|rdtscp|scasq|stosq|swapgs)(?-i)\\b" + - statement: "\\b(?i)(clgi|invlpga|skinit|stgi|vmload|vmmcall|vmrun|vmsave)(?-i)\\b" + - statement: "\\b(?i)(vmptrdl|vmptrst|vmclear|vmread|vmwrite|vmcall|vmlaunch|vmresume|vmxoff|vmxon)(?-i)\\b" + - statement: "\\b(?i)(lzcnt|popcnt)(?-i)\\b" + - statement: "\\b(?i)(bextr|blcfill|blci|blcic|blcmask|blcs|blsfill|blsic|t1mskc|tzmsk)(?-i)\\b" + + # x87 + - statement: "\\b(?i)(f2xm1|fabs|fadd|faddp|fbld|fbstp|fchs|fclex|fcom|fcomp|fcompp|fdecstp|fdisi|fdiv|fvidp|fdivr|fdivrp|feni|ffree|fiadd|ficom|ficomp|fidiv|fidivr|fild|fimul|fincstp|finit|fist|fistp|fisub|fisubr|fld|fld1|fldcw|fldenv|fldenvw|fldl2e|fldl2t|fldlg2|fldln2|fldpi|fldz|fmul|fmulp|fnclex|fndisi|fneni|fninit|fnop|fnsave|fnsavenew|fnstcw|fnstenv|fnstenvw|fnstsw|fpatan|fprem|fptan|frndint|frstor|frstorw|fsave|fsavew|fscale|fsqrt|fst|fstcw|fstenv|fstenvw|fstp|fstpsw|fsub|fsubp|fsubr|fsubrp|ftst|fwait|fxam|fxch|fxtract|fyl2x|fyl2xp1)(?-i)\\b" + - statement: "\\b(?i)(fsetpm)(?-i)\\b" + - statement: "\\b(?i)(fcos|fldenvd|fsaved|fstenvd|fprem1|frstord|fsin|fsincos|fstenvd|fucom|fucomp|fucompp)(?-i)\\b" + - statement: "\\b(?i)(fcmovb|fcmovbe|fcmove|fcmove|fcmovnb|fcmovnbe|fcmovne|fcmovnu|fcmovu)(?-i)\\b" + - statement: "\\b(?i)(fcomi|fcomip|fucomi|fucomip)(?-i)\\b" + - statement: "\\b(?i)(fxrstor|fxsave)(?-i)\\b" + - statement: "\\b(?i)(fisttp)(?-i)\\b" + - statement: "\\b(?i)(ffreep)(?-i)\\b" + + # SIMD + - statement: "\\b(?i)(emms|movd|movq|packssdw|packsswb|packuswb|paddb|paddw|paddd|paddsb|paddsw|paddusb|paddusw|pand|pandn|por|pxor|pcmpeqb|pcmpeqw|pcmpeqd|pcmpgtb|pcmpgtw|pcmpgtd|pmaddwd|pmulhw|pmullw|psllw|pslld|psllq|psrad|psraw|psrlw|psrld|psrlq|psubb|psubw|psubd|psubsb|psubsw|psubusb|punpckhbw|punpckhwd|punpckhdq|punkcklbw|punpckldq|punpcklwd)(?-i)\\b" + - statement: "\\b(?i)(paveb|paddsiw|pmagw|pdistib|psubsiw|pmwzb|pmulhrw|pmvnzb|pmvlzb|pmvgezb|pmulhriw|pmachriw)(?-i)\\b" + - statement: "\\b(?i)(femms|pavgusb|pf2id|pfacc|pfadd|pfcmpeq|pfcmpge|pfcmpgt|pfmax|pfmin|pfmul|pfrcp|pfrcpit1|pfrcpit2|pfrsqit1|pfrsqrt|pfsub|pfsubr|pi2fd|pmulhrw|prefetch|prefetchw)(?-i)\\b" + - statement: "\\b(?i)(pf2iw|pfnacc|pfpnacc|pi2fw|pswapd)(?-i)\\b" + - statement: "\\b(?i)(pfrsqrtv|pfrcpv)(?-i)\\b" + - statement: "\\b(?i)(addps|addss|cmpps|cmpss|comiss|cvtpi2ps|cvtps2pi|cvtsi2ss|cvtss2si|cvttps2pi|cvttss2si|divps|divss|ldmxcsr|maxps|maxss|minps|minss|movaps|movhlps|movhps|movlhps|movlps|movmskps|movntps|movss|movups|mulps|mulss|rcpps|rcpss|rsqrtps|rsqrtss|shufps|sqrtps|sqrtss|stmxcsr|subps|subss|ucomiss|unpckhps|unpcklps)(?-i)\\b" + - statement: "\\b(?i)(andnps|andps|orps|pavgb|pavgw|pextrw|pinsrw|pmaxsw|pmaxub|pminsw|pminub|pmovmskb|pmulhuw|psadbw|pshufw|xorps)(?-i)\\b" + - statement: "\\b(?i)(movups|movss|movlps|movhlps|movlps|unpcklps|unpckhps|movhps|movlhps|prefetchnta|prefetch0|prefetch1|prefetch2|nop|movaps|cvtpi2ps|cvtsi2ss|cvtps2pi|cvttss2si|cvtps2pi|cvtss2si|ucomiss|comiss|sqrtps|sqrtss|rsqrtps|rsqrtss|rcpps|andps|orps|xorps|addps|addss|mulps|mulss|subps|subss|minps|minss|divps|divss|maxps|maxss|pshufw|ldmxcsr|stmxcsr|sfence|cmpps|cmpss|pinsrw|pextrw|shufps|pmovmskb|pminub|pmaxub|pavgb|pavgw|pmulhuw|movntq|pminsw|pmaxsw|psadbw|maskmovq)(?-i)\\b" + - statement: "\\b(?i)(addpd|addsd|addnpd|cmppd|cmpsd)(?-i)\\b" + - statement: "\\b(?i)(addpd|addsd|andnpd|andpd|cmppd|cmpsd|comisd|cvtdq2pd|cvtdq2ps|cvtpd2dq|cvtpd2pi|cvtpd2ps|cvtpi2pd|cvtps2dq|cvtps2pd|cvtsd2si|cvtsd2ss|cvtsi2sd|cvtss2sd|cvttpd2dq|cvttpd2pi|cvttps2dq|cvttsd2si|divpd|divsd|maxpd|maxsd|minpd|minsd|movapd|movhpd|movlpd|movmskpd|movsd|movupd|mulpd|mulsd|orpd|shufpd|sqrtpd|sqrtsd|subpd|subsd|ucomisd|unpckhpd|unpcklpd|xorpd)(?-i)\\b" + - statement: "\\b(?i)(movdq2q|movdqa|movdqu|movq2dq|paddq|psubq|pmuludq|pshufhw|pshuflw|pshufd|pslldq|psrldq|punpckhqdq|punpcklqdq)(?-i)\\b" + - statement: "\\b(?i)(addsubpd|addsubps|haddpd|haddps|hsubpd|hsubps|movddup|movshdup|movsldu)(?-i)\\b" + - statement: "\\b(?i)(lddqu)(?-i)\\b" + - statement: "\\b(?i)(psignw|psignd|psignb|pshufb|pmulhrsw|pmaddubsw|phsubw|phsubsw|phsubd|phaddw|phaddsw|phaddd|palignr|pabsw|pabsd|pabsb)(?-i)\\b" + - statement: "\\b(?i)(dpps|dppd|blendps|blendpd|blendvps|blendvpd|roundps|roundss|roundpd|roundsd|insertps|extractps)(?-i)\\b" + - statement: "\\b(?i)(mpsadbw|phminposuw|pmulld|pmuldq|pblendvb|pblendw|pminsb|pmaxsb|pminuw|pmaxuw|pminud|pmaxud|pminsd|pmaxsd|pinsrb|pinsrd/pinsrq|pextrb|pextrw|pextrd/pextrq|pmovsxbw|pmovzxbw|pmovsxbd|pmovzxbd|pmovsxbq|pmovzxbq|pmovsxwd|pmovzxwd|pmovsxwq|pmovzxwq|pmovsxdq|pmovzxdq|ptest|pcmpeqq|packusdw|movntdqa)(?-i)\\b" + - statement: "\\b(?i)(extrq|insertq|movntsd|movntss)(?-i)\\b" + - statement: "\\b(?i)(crc32|pcmpestri|pcmpestrm|pcmpistri|pcmpistrm|pcmpgtq)(?-i)\\b" + - statement: "\\b(?i)(vfmaddpd|vfmaddps|vfmaddsd|vfmaddss|vfmaddsubpd|vfmaddsubps|vfmsubaddpd|vfmsubaddps|vfmsubpd|vfmsubps|vfmsubsd|vfmsubss|vfnmaddpd|vfnmaddps|vfnmaddsd|vfnmaddss|vfnmsubps|vfnmsubsd|vfnmsubss)(?-i)\\b" + + # Crypto + - statement: "\\b(?i)(aesenc|aesenclast|aesdec|aesdeclast|aeskeygenassist|aesimc)(?-i)\\b" + - statement: "\\b(?i)(sha1rnds4|sha1nexte|sha1msg1|sha1msg2|sha256rnds2|sha256msg1|sha256msg2)(?-i)\\b" + + # Undocumented + - statement: "\\b(?i)(aam|aad|salc|icebp|loadall|loadalld|ud1)(?-i)\\b" + + ## Registers + - identifier: "\\b(?i)(al|ah|bl|bh|cl|ch|dl|dh|bpl|sil|r8b|r9b|r10b|r11b|dil|spl|r12b|r13b|r14b|r15)(?-i)\\b" + - identifier: "\\b(?i)(cw|sw|tw|fp_ds|fp_opc|fp_ip|fp_dp|fp_cs|cs|ss|ds|es|fs|gs|gdtr|idtr|tr|ldtr|ax|bx|cx|dx|bp|si|r8w|r9w|r10w|r11w|di|sp|r12w|r13w|r14w|r15w|ip)(?-i)\\b" + - identifier: "\\b(?i)(fp_dp|fp_ip|eax|ebx|ecx|edx|ebp|esi|r8d|r9d|r10d|r11d|edi|esp|r12d|r13d|r14d|r15d|eip|eflags|mxcsr)(?-i)\\b" + - identifier: "\\b(?i)(mm0|mm1|mm2|mm3|mm4|mm5|mm6|mm7|rax|rbx|rcx|rdx|rbp|rsi|r8|r9|r10|r11|rdi|rsp|r12|r13|r14|r15|rip|rflags|cr0|cr1|cr2|cr3|cr4|cr5|cr6|cr7|cr8|cr9|cr10|cr11|cr12|cr13|cr14|cr15|msw|dr0|dr1|dr2|dr3|r4|dr5|dr6|dr7|dr8|dr9|dr10|dr11|dr12|dr13|dr14|dr15)(?-i)\\b" + - identifier: "\\b(?i)(st0|st1|st2|st3|st4|st5|st6|st7)(?-i)\\b" + - identifier: "\\b(?i)(xmm0|xmm1|xmm2|xmm3|xmm4|xmm5|xmm6|xmm7|xmm8|xmm9|xmm10|xmm11|xmm12|xmm13|xmm14|xmm15)(?-i)\\b" + - identifier: "\\b(?i)(ymm0|ymm1|ymm2|ymm3|ymm4|ymm5|ymm6|ymm7|ymm8|ymm9|ymm10|ymm11|ymm12|ymm13|ymm14|ymm15)(?-i)\\b" + - identifier: "\\b(?i)(zmm0|zmm1|zmm2|zmm3|zmm4|zmm5|zmm6|zmm7|zmm8|zmm9|zmm10|zmm11|zmm12|zmm13|zmm14|zmm15|zmm16|zmm17|zmm18|zmm19|zmm20|zmm21|zmm22|zmm23|zmm24|zmm25|zmm26|zmm27|zmm28|zmm29|zmm30|zmm31)(?-i)\\b" + + ## Constants + # Number - it works + - constant.number: "\\b(|h|A|0x)+[0-9]+(|h|A)+\\b" + - constant.number: "\\b0x[0-9 a-f A-F]+\\b" + + ## Preprocessor (NASM) + - preproc: "%+(\\+|\\?|\\?\\?|)[a-z A-Z 0-9]+" + - preproc: "%\\[[. a-z A-Z 0-9]*\\]" + + ## Other + - statement: "\\b(?i)(extern|global|section|segment|_start|\\.text|\\.data|\\.bss)(?-i)\\b" + - statement: "\\b(?i)(db|dw|dd|dq|dt|ddq|do)(?-i)\\b" + - identifier: "[a-z A-Z 0-9 _]+:" + + - constant.string: + start: "\"" + end: "\"" + rules: + - constant.specialChar: "\\\\." + + - constant.string: + start: "'" + end: "'" + rules: + - constant.specialChar: "\\\\." + + - comment: + start: ";" + end: "$" + rules: + - todo: "(TODO|XXX|FIXME):?" diff --git a/runtime/syntax/c.yaml b/runtime/syntax/c.yaml index 5f4bfae1..a3974483 100644 --- a/runtime/syntax/c.yaml +++ b/runtime/syntax/c.yaml @@ -39,9 +39,11 @@ rules: - comment: start: "//" end: "$" - rules: [] + rules: + - todo: "(TODO|XXX|FIXME):?" - comment: start: "/\\*" end: "\\*/" - rules: [] + rules: + - todo: "(TODO|XXX|FIXME):?" diff --git a/runtime/syntax/caddyfile.yaml b/runtime/syntax/caddyfile.yaml new file mode 100644 index 00000000..7c386f18 --- /dev/null +++ b/runtime/syntax/caddyfile.yaml @@ -0,0 +1,21 @@ +filetype: caddyfile + +detect: + filename: "Caddyfile" + +rules: + - identifier: "^\\s*\\S+(\\s|$)" + - type: "^([\\w.:/-]+,? ?)+[,{]$" + - constant.specialChar: "\\s{$" + - constant.specialChar: "^\\s*}$" + - constant.string: + start: "\"" + end: "\"" + rules: + - constant.specialChar: "\\\\." + + - preproc: "\\{(\\w+|\\$\\w+|%\\w+%)\\}" + - comment: + start: "#" + end: "$" + rules: [] diff --git a/runtime/syntax/coffeescript.yaml b/runtime/syntax/coffeescript.yaml new file mode 100644 index 00000000..30ae1dc1 --- /dev/null +++ b/runtime/syntax/coffeescript.yaml @@ -0,0 +1,27 @@ +filetype: coffeescript + +detect: + filename: "\\.coffee$" + +rules: + - statement: "[!&|=/*+-<>]|\\b(and|or|is|isnt|not)\\b" + - identifier: "([A-Za-z_][A-Za-z0-9_]*:[[:space:]]*(->|\\()|->)" + - statement: "[()]" + - statement: "\\b(for|of|continue|break|isnt|null|unless|this|else|if|return)\\b" + - statement: "\\b(try|catch|finally|throw|new|delete|typeof|in|instanceof)\\b" + - statement: "\\b(debugger|switch|while|do|class|extends|super)\\b" + - statement: "\\b(undefined|then|unless|until|loop|of|by|when)\\b" + - constant: "\\b(true|false|yes|no|on|off)\\b" + - preproc: "@[A-Za-z0-9_]*" + + - constant.string: + start: "\"" + end: "\"" + rules: + - constant.specialChar: "\\\\." + + - comment: + start: "#" + end: "$" + rules: + - todo: "(TODO|XXX|FIXME):?" diff --git a/runtime/syntax/dockerfile.yaml b/runtime/syntax/dockerfile.yaml new file mode 100644 index 00000000..3481dc9a --- /dev/null +++ b/runtime/syntax/dockerfile.yaml @@ -0,0 +1,33 @@ +filetype: dockerfile + +detect: + filename: "(Dockerfile[^/]*$|\\.dockerfile$)" + +rules: + ## Keywords + - keyword: "(?i)^(FROM|MAINTAINER|RUN|CMD|LABEL|EXPOSE|ENV|ADD|COPY|ENTRYPOINT|VOLUME|USER|WORKDIR|ONBUILD|ARG|HEALTHCHECK|STOPSIGNAL|SHELL)[[:space:]]" + + ## Brackets & parenthesis + - statement: "(\\(|\\)|\\[|\\])" + + ## Double ampersand + - special: "&&" + + ## Comments + - comment: + start: "#" + end: "$" + rules: + - todo: "(TODO|XXX|FIXME):?" + + - constant.string: + start: "\"" + end: "\"" + rules: + - constant.specialChar: "\\\\." + + - constant.string: + start: "'" + end: "'" + rules: + - constant.specialChar: "\\\\." diff --git a/runtime/syntax/go.yaml b/runtime/syntax/go.yaml index 3103e60a..44bd570d 100644 --- a/runtime/syntax/go.yaml +++ b/runtime/syntax/go.yaml @@ -1,7 +1,7 @@ filetype: go detect: - filename: "\\.go$" + filename: "\\.go$" rules: - statement: "\\b(break|case|continue|default|else|for|go|goto|if|range|return|switch)\\b" diff --git a/runtime/syntax/syntax_checker.go b/runtime/syntax/syntax_checker.go new file mode 100644 index 00000000..20d2e1db --- /dev/null +++ b/runtime/syntax/syntax_checker.go @@ -0,0 +1,30 @@ +package main + +import ( + "fmt" + "io/ioutil" + "strings" + + "github.com/zyedidia/micro/cmd/micro/highlight" +) + +func main() { + files, _ := ioutil.ReadDir(".") + + hadErr := false + for _, f := range files { + if strings.HasSuffix(f.Name(), ".yaml") { + input, _ := ioutil.ReadFile("/Users/zachary/gocode/src/github.com/zyedidia/highlight/syntax_files/" + f.Name()) + _, err := highlight.ParseDef(input) + if err != nil { + hadErr = true + fmt.Printf("%s:\n", f.Name()) + fmt.Println(err) + continue + } + } + } + if !hadErr { + fmt.Println("No issues!") + } +}