Skip to content

Instantly share code, notes, and snippets.

@yvt
Created October 28, 2013 13:33
Show Gist options
  • Save yvt/7196851 to your computer and use it in GitHub Desktop.
Save yvt/7196851 to your computer and use it in GitHub Desktop.
Queen HTML ハイライター
{
ArrayList.qn
tcpp が 2013年10月28日 に作成.
}
interface IFormatter`T
func Format(v:T): string
end interface
class ArrayList`T
-var arr: []T :: #[4]T
-var count: int
-var capacity: int :: 4
func EnsureCapacity(cnt: int)
var c: int :: capacity
while(c < cnt)
c :* 2
end while
if(c <> capacity)
var arr2: []T :: #[c]T
for i(0, count - 1)
arr2[i] :: arr[i]
end for
arr :: arr2
capacity :: c
end if
end func
func Add(v: T)
EnsureCapacity(count + 1)
arr[count] :: v
count :+ 1
end func
func AddArray(a: []T)
EnsureCapacity(count + a.Len())
foreach v(a)
arr[count] :: v
count :+ 1
end foreach
end func
func Clear()
count :: 0
end func
func Get(idx: int): T
return arr[idx]
end func
func Set(idx: int, val: T)
arr[idx] :: val
end func
func GetLen(): int
return count
end func
func ToArray(): []T
var arr2: []T :: #[count]T
for i(0, count - 1)
arr2[i] :: arr[i]
end for
return arr2
end func
func Dump(formatter: IFormatter`T)
Dbg@Log("Elements: ------")
for i(0, count - 1)
Dbg@Log("[" ~ i.ToStr() ~ "] = " ~ formatter.Format(arr[i]))
end for
Dbg@Log("-----------------")
end func
end class
{ プログラムのエントリポイントを定義します。 }
var text: string:: "
{ エラトステネスのふるい実装 }
class PrimeGenesis
var primes: []int:: #[10000]int
var numPrimes: int
func Ctor()
primes[0] :: 2
numPrimes :: 1
end func
-func IsComposite(x: int): bool
foreach prime (primes)
if( prime = 0 )
return false
elif( x % prime = 0 )
return true
end if
end foreach
return false
end func
func GetNext(): int
var i:: primes[numPrimes - 1] + 1
while (IsComposite(i))
i :+ 1
end while
primes[numPrimes] :: i
numPrimes :+ 1
return i
end func
end class
{ AppMainが定義されると、ゲームエンジンの代わりに呼び出されます。 }
func AppMain()
var primes:: #PrimeGenesis
var sum:: 2
var startTime:: Time@Sys()
for (2, 10000)
sum :+ primes.GetNext()
end for
var duration:: (Time@Sys() - startTime)$float / 1000.0
Dbg@Log(\"10000番目までの素数の和 = \" ~ sum.ToStr() ~ \" (\" ~ duration.ToStr() ~ \" 秒)\")
Q@Stop()
end func
"
enum KeywordType
NotKeyword
Type
Literal
Statement
TypeDefinition
end enum
func ConvertCharIndex(c: char): int
switch(c)
case ('0' to '9')
return c$int - '0'$int
case ('a' to 'z')
return c$int - 'a'$int + 10
case ('A' to 'Z')
return c$int - 'A'$int + 36
case ('_')
return 63
end switch
return -1
end func
class KeywordTree
var type: KeywordType
var sub: []KeywordTree
func Register(str: []char, type: KeywordType, index: int)
if(index = str.Len())
this.type :: type
return
end if
if(sub =& null)
sub :: #[26 * 2 + 10 + 1]KeywordTree
end if
var idx:: ConvertCharIndex(str[index])
if(idx = -1)
throw 2000, "damemoji! " ~ str
end if
if(sub[idx] =& null)
sub[idx] :: #KeywordTree
end if
sub[idx].Register(str, type, index + 1)
end func
func Advance(c: char): KeywordTree
if (sub =& null)
return null
end if
var idx:: ConvertCharIndex(c)
if (idx = -1)
return null
end if
return sub[idx]
end func
end class
func IsIdentifierChar(c: char): bool
switch(c)
case ('a' to 'z')
return true
case ('A' to 'Z')
return true
case ('_')
return true
case ('0' to '9')
return true
default
return false
end switch
end func
func AppMain()
var code:: text$[]char
var root:: #KeywordTree
root.Register("byte", KeywordType#Type, 0)
root.Register("byte8", KeywordType#Type, 0)
root.Register("byte16", KeywordType#Type, 0)
root.Register("byte32", KeywordType#Type, 0)
root.Register("byte64", KeywordType#Type, 0)
root.Register("dict", KeywordType#Type, 0)
root.Register("bool", KeywordType#Type, 0)
root.Register("float", KeywordType#Type, 0)
root.Register("double", KeywordType#Type, 0)
root.Register("list", KeywordType#Type, 0)
root.Register("queue", KeywordType#Type, 0)
root.Register("stack", KeywordType#Type, 0)
{ root.Register("func", KeywordType#Type, 0) }
root.Register("int", KeywordType#Type, 0)
root.Register("int8", KeywordType#Type, 0)
root.Register("int16", KeywordType#Type, 0)
root.Register("int32", KeywordType#Type, 0)
root.Register("int64", KeywordType#Type, 0)
root.Register("uint8", KeywordType#Type, 0)
root.Register("uint16", KeywordType#Type, 0)
root.Register("uint32", KeywordType#Type, 0)
root.Register("uint64", KeywordType#Type, 0)
root.Register("string", KeywordType#Type, 0)
root.Register("char", KeywordType#Type, 0)
root.Register("inf", KeywordType#Literal, 0)
root.Register("true", KeywordType#Literal, 0)
root.Register("this", KeywordType#Literal, 0)
root.Register("false", KeywordType#Literal, 0)
root.Register("assert", KeywordType#Statement, 0)
root.Register("block", KeywordType#Statement, 0)
root.Register("break", KeywordType#Statement, 0)
root.Register("continue", KeywordType#Statement, 0)
root.Register("catch", KeywordType#Statement, 0)
root.Register("default", KeywordType#Statement, 0)
root.Register("do", KeywordType#Statement, 0)
root.Register("elif", KeywordType#Statement, 0)
root.Register("else", KeywordType#Statement, 0)
root.Register("end", KeywordType#Statement, 0)
root.Register("finally", KeywordType#Statement, 0)
root.Register("for", KeywordType#Statement, 0)
root.Register("foreach", KeywordType#Statement, 0)
root.Register("func", KeywordType#Statement, 0)
root.Register("if", KeywordType#Statement, 0)
root.Register("ifdef", KeywordType#Statement, 0)
root.Register("return", KeywordType#Statement, 0)
root.Register("rls", KeywordType#Statement, 0)
root.Register("dbg", KeywordType#Statement, 0)
root.Register("skip", KeywordType#Statement, 0)
root.Register("switch", KeywordType#Statement, 0)
root.Register("case", KeywordType#Statement, 0)
root.Register("throw", KeywordType#Statement, 0)
root.Register("to", KeywordType#Statement, 0)
root.Register("try", KeywordType#Statement, 0)
root.Register("var", KeywordType#Statement, 0)
root.Register("while", KeywordType#Statement, 0)
root.Register("const", KeywordType#Statement, 0)
root.Register("class", KeywordType#Statement, 0)
root.Register("enum", KeywordType#Statement, 0)
root.Register("interface", KeywordType#Statement, 0)
enum BlockState
Normal
StringLiteral
CharLiteral
end enum
func EmitKeywordSpan(type: KeywordType): []char
switch(type)
case(KeywordType#Type)
return "<span class=\"kwType\">"
case(KeywordType#Statement)
return "<span class=\"kwStatement\">"
case(KeywordType#Literal)
return "<span class=\"kwLiteral\">"
default
assert false
end switch
return null
end func
func EmitBlockSpan(type: BlockState): []char
switch(type)
case(BlockState#StringLiteral)
return "<span class=\"bString\">"
case(BlockState#CharLiteral)
return "<span class=\"bChar\">"
default
assert false
end switch
return null
end func
func EmitChar(arr: ArrayList@ArrayList`char, c: char)
switch(c)
case ('<')
arr.AddArray("&lt;")
case ('>')
arr.AddArray("&gt;")
case ('"')
arr.AddArray("&quot;")
default
arr.Add(c)
end switch
end func
var output:: #ArrayList@ArrayList`char
var token:: #ArrayList@ArrayList`char
var commentDepth:: 0
var state:: BlockState#Normal
var tree: KeywordTree:: null
var scanningIdentifier:: false
for i(0, code.Len() - 1)
var c:: code[i]
if(commentDepth > 0)
output.Add(c)
if(c = '}')
commentDepth :- 1
if(commentDepth = 0)
output.AddArray("</span>")
end if
elif(c = '{')
commentDepth :+ 1
end if
else
switch(state)
case (BlockState#Normal)
if(IsIdentifierChar(c))
if(scanningIdentifier)
token.Add(c)
tree :: (tree =& null) ? (null, tree.Advance(c))
else
tree :: root.Advance(c)
token.Add(c)
scanningIdentifier :: true
end if
else
if(scanningIdentifier)
if(tree <>& null & tree.type <> KeywordType#NotKeyword)
output.AddArray(EmitKeywordSpan(tree.type))
output.AddArray(token.ToArray())
output.AddArray("</span>")
token.Clear()
else
output.AddArray(token.ToArray())
token.Clear()
end if
end if
tree :: null
scanningIdentifier :: false
switch(c)
case ('{')
commentDepth :+ 1
output.AddArray("<span class=\"codeComment\">")
case ('"')
state :: BlockState#StringLiteral
output.AddArray(EmitBlockSpan(state))
case ('\'')
state :: BlockState#CharLiteral
output.AddArray(EmitBlockSpan(state))
end switch
output.Add(c)
end if
case (BlockState#StringLiteral)
EmitChar(output, c)
if(c = '\\')
i :+ 1
EmitChar(output, code[i])
elif(c = '"')
state :: BlockState#Normal
output.AddArray("</span>")
end if
case (BlockState#CharLiteral)
EmitChar(output, c)
if(c = '\\')
i :+ 1
EmitChar(output, code[i])
elif(c = '\'')
state:: BlockState#Normal
output.AddArray("</span>")
end if
default
assert false
end switch
end if
end for
Dbg@Log(output.ToArray())
Q@Stop()
end func
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment