Files
vulcan/vweb/src/forge_highlighter.js
T
2024-05-01 23:19:26 -05:00

97 lines
4.1 KiB
JavaScript

export default {
name: 'forge',
startState: function () {
// asm is "have we seen the asm keyword." The first time we see braces after that keyword (ignoring
// strings, because string literals in an asm arg block is legal) we start highlighting it as asm.
// The current state is just the current state, null means normal.
return {current: null, asm: false}
},
token: function (stream, state) {
if (stream.eatSpace()) return null
if (state.current === null) {
let word
if (word = stream.match(/^[a-zA-Z_$][a-zA-Z0-9_$]*/)) {
// This is either a keyword or an identifier.
// All the keywords are valid names, so, check that:
if (word[0].match(/^fn|var|new|static|asm|return|if|while|repeat|global|const$/)) {
if (word[0] === 'asm') {
state.asm = true
} // This is the start of an asm control structure
return 'keyword'
} else {
return 'variable'
}
} else if (stream.match(/^-?((0b[01]+)|(0x[0-9a-fA-F]+)|(0o[0-7]+)|0|([1-9][0-9]*?))/)) {
// All the number formats. Unary minus is just an operator
return 'number'
} else if (stream.match(/^"/)) {
// Open quote to start a string
state.current = 'string'
return 'string'
} else if (stream.match(/^{/)) {
// Open brace
if (state.asm) {
// This is the start of the _actual_ asm block, kick us into asm mode and gooooo
state.current = 'asm'
state.asm = false // clear the flag
return 'quote'
} else {
// A normal open brace, just highlight it. If we do indentation stuff it goes here.
return 'strong'
}
} else if (stream.match(/^[};]/)) {
// Close brace and semicolon get bolded.
return 'strong'
} else if (stream.match(/^\/\/.*/)) {
// Normal line comment
return 'comment'
} else if (stream.match(/^\/\*/)) {
// Start of a block comment, switch our mode
state.current = 'comment'
return 'comment'
} else if (stream.match(/^&&|\|\||==|!=|>=|<=|[-+*/%&|^><=]/)) {
// These operators have to be after the comment check
return 'operator'
} else {
// Dunno what this is, so just return content
stream.next()
return 'content'
}
} else if (state.current === 'comment') {
// We're in a block comment
if (stream.match(/^\*\//)) {
// End of a block comment, clear the state
state.current = null
} else {
// Have to move forward
stream.next()
}
return 'comment' // No matter whether we clear the state or not, it's still currently a comment
} else if (state.current === 'string') {
// We're in a string
if (stream.match(/^"/)) {
// We're no longer in a string
state.current = null
} else {
// If the next char is a backslash...
stream.eat(/^\\/)
stream.next() // Advance past the _next_ char, skip whatever the escape is.
}
return 'string'
} else if (state.current === 'asm') {
// We're in an asm block
if (stream.match(/^}/)) {
// asm blocks end on close-brace, whether quoted or not! Forge is unaware of any brace rules in
// the assembler. This is a reality in the compiler as well, not just this highlighter.
state.current = null
} else {
// If it's not a brace move forward anyway
stream.next()
}
return 'quote'
}
}
}