1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/str-go-spp

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
В этом репозитории не указан файл с открытой лицензией (LICENSE). При использовании обратитесь к конкретному описанию проекта и его зависимостям в коде.
Клонировать/Скачать
spp.go 33 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
songzhiquan Отправлено 15.06.2018 07:23 da3218b
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599
package main
import (
"fmt"
"io/ioutil"
"os"
"bufio"
"strconv"
"strings"
"unicode/utf8"
"path/filepath"
)
type Str = string
type Int = int
type Bool = bool
type Strs = []string
type Ints = []int
type Estrs = []Ints
type Table = map[string]string
type Tree = map[string]Table
func sprintf(format string, x ...interface{}) string {
return fmt.Sprintf(format, x...)
}
func error(s string) {
println(s)
os.Exit(1)
}
func stdin() string {
reader := bufio.NewReader(os.Stdin)
line, _ := reader.ReadString('\n')
return line
}
func ord(s string) Int {
_c, _ := utf8.DecodeRuneInString(s)
return int(_c)
}
func trim(s string) string {
return strings.TrimSpace(s)
}
func split(sep, s string) []string {
return strings.Split(s, sep)
}
func to_chars(s string) Strs {
_runes := []rune(s)
_strs := []string{}
for _, _rune := range _runes {
_strs = append(_strs, string(_rune))
}
return _strs
}
func to_ints(s string) Ints {
_runes := []rune(s)
_ints := []int{}
for _, _rune := range _runes {
_ints = append(_ints, int(_rune))
}
return _ints
}
func join(sep string, a Strs) string {
return strings.Join(a, sep)
}
func add(a ...string) string {
return to_str(a)
}
func to_str(a []string) string {
return strings.Join(a, ``)
}
func exists(ns Table, key string) bool {
_, ok := ns[key]
return ok
}
func is_exists(table Tree, keys ...string) bool {
key1 := keys[0]
_, ok := table[key1]
if len(keys) == 1 { return ok }
key2 := keys[1]
_, ok2 := table[key1][key2]
return ok2
}
func is_in(s string, a []string) bool {
for _, _s := range a {
if _s == s { return true }
}
return false
}
func end_with(s, suffix string) bool {
return strings.HasSuffix(s, suffix)
}
func start_with(s, prefix string) bool {
return strings.HasPrefix(s, prefix)
}
func repeat(s string, count int) string {
return strings.Repeat(s, count)
}
func index(s, substr string) int {
return strings.Index(s, substr)
}
func ucfirst(s string) string {
_first_char := strings.ToUpper(first_char(s))
return _first_char + rest_str(s)
}
func first_char(s string) string {
_char := s[0]
return string(_char)
}
func last_char(s string) string {
return string(s[len(s)-1])
}
func rest_str(s string) string {
return s[1:]
}
func chop(s string) string {
return s[0:len(s)-1]
}
func cut(s string) string {
return s[1:len(s)-1]
}
func first(a []string) string { return a[0] }
func last(a []string) string { return a[len(a)-1] }
func rest(a []string) []string { return a[1:] }
func to_s(i int) string {
return strconv.Itoa(i)
}
func to_i(s string) int {
i, err := strconv.Atoi(s)
if err != nil {
panic(err)
}
return i
}
func Map(mapping func(string) string, ra []string) []string {
var ra_map []string
for _, x := range ra {
ra_map = append(ra_map, mapping(x))
}
return ra_map
}
func to_end(s string, i int) string {
sub_s := s[i:]
if index(sub_s, "\n") == -1 { return sub_s }
index := index(sub_s, "\n")
return sub_s[0:index]
}
func aflat(array []string) (string, string) {
return array[0], array[1]
}
func amatch(array []string) (string, []string) {
return array[0], rest(array)
}
func basename(_file string) string {
return filepath.Base(_file)
}
func rename_file(from_file, to_file string) {
if file_exists(from_file) {
os.Rename(from_file, to_file)
}
}
func bak_file(_file string) {
if file_exists(_file) {
_basename := basename(_file)
os.Rename(_file, sprintf("Bak/%s",_basename))
}
}
func file_exists(_file string) bool {
if _, err := os.Stat(_file); err == nil {
return true
}
fmt.Printf("file: %s not exists!\n", _file)
return false
}
func read_file(file string) string {
str_bytes, err := ioutil.ReadFile(file)
if err != nil {
fmt.Printf("file %s not exists!", file)
}
return string(str_bytes)
}
func write_file(file string, s string) {
x_data := []byte(s)
err := ioutil.WriteFile(file, x_data, 0777)
if err != nil { panic(err) }
}
func is_alpha(_c Str) Bool {
if is_lower(_c) {
return true
}
if is_upper(_c) {
return true
}
if _c == `_` {
return true
}
return false
}
func is_digit(_c Str) Bool {
_int := ord(_c)
if _int >= 48 {
if _int <= 57 {
return true
}
}
return false
}
func is_hspace(_c Str) Bool {
if _c == string(9) {
return true
}
if _c == string(32) {
return true
}
return false
}
func is_lower(_c Str) Bool {
_int := ord(_c)
if _int >= 97 {
if _int <= 122 {
return true
}
}
return false
}
func is_space(_c Str) Bool {
if is_hspace(_c) {
return true
}
if is_vspace(_c) {
return true
}
return false
}
func is_upper(_c Str) Bool {
_int := ord(_c)
if _int >= 65 {
if _int <= 90 {
return true
}
}
return false
}
func is_vspace(_c Str) Bool {
if _c == string(10) {
return true
}
if _c == string(13) {
return true
}
return false
}
func is_words(_c Str) Bool {
if is_digit(_c) {
return true
}
if is_alpha(_c) {
return true
}
return false
}
func is_xdigit(_c Str) Bool {
if is_digit(_c) {
return true
}
_int := ord(_c)
if _int >= 65 {
if _int <= 70 {
return true
}
}
if _int >= 97 {
if _int <= 102 {
return true
}
}
return false
}
func is_oper(_str Str) Bool {
_ochars := `-+=><!~`
for _, _char := range to_chars(_str) {
if index(_ochars, _char) == -1 {
return false
}
}
return true
}
func is_str(_str Str) Bool {
_char := first_char(_str)
return ord(_char) > 5
}
func is_estr(_str Str) Bool {
return first_char(_str) == string(3)
}
func is_atom(_atom Str) Bool {
if first_char(_atom) == string(3) {
if string(_atom[1]) == string(5) {
return true
}
}
return false
}
func is_blank(_str Str) Bool {
return _str == add(string(3), string(4))
}
func estr_atom(_atom Str) Str {
if is_estr(_atom) {
return _atom
}
return add(string(5), _atom)
}
func estr(_args ...Str) Str {
return estr_strs(_args)
}
func estr_strs(_array Strs) Str {
_estr := to_str(Map(estr_atom, _array))
return add(string(3), _estr, string(4))
}
func from_ejson(_json Str) Str {
_chars := []string{}
_mode := 0
for _, _ch := range to_chars(_json) {
if _mode == 0 {
switch _ch {
case `[`: {
_chars = append(_chars, string(3))
}
case `]`: {
_chars = append(_chars, string(4))
}
case `"`: {
_chars = append(_chars, string(5))
_mode = 1
}
}
} else if _mode == 1 {
switch _ch {
case `"`: {
_mode = 0
}
case string(92): {
_mode = 2
}
default: {
_chars = append(_chars, _ch)
}
}
} else {
_mode = 1
switch _ch {
case `t`: {
_chars = append(_chars, string(9))
}
case `n`: {
_chars = append(_chars, string(10))
}
case `r`: {
_chars = append(_chars, string(13))
}
default: {
_chars = append(_chars, _ch)
}
}
}
}
return to_str(_chars)
}
func to_ejson(_estr Str) Str {
if is_str(_estr) {
return _estr
}
_chars := []string{}
_mode := 0
for _, _ch := range to_chars(_estr) {
if _mode == 0 {
switch _ch {
case string(3): {
_chars = append(_chars, `[`)
}
case string(5): {
_chars = append(_chars, `"`)
_mode = 1
}
case string(4): {
_chars = append(_chars, `]`)
_mode = 2
}
}
} else if _mode == 1 {
switch _ch {
case string(3): {
_chars = append(_chars, `",[`)
_mode = 0
}
case string(5): {
_chars = append(_chars, `","`)
}
case string(4): {
_chars = append(_chars, `"]`)
_mode = 2
}
default: {
_chars = append(_chars, char_to_ejson(_ch))
}
}
} else {
switch _ch {
case string(3): {
_chars = append(_chars, `,[`)
_mode = 0
}
case string(5): {
_chars = append(_chars, `,"`)
_mode = 1
}
case string(4): {
_chars = append(_chars, `]`)
}
}
}
}
return to_str(_chars)
}
func char_to_ejson(_ch Str) Str {
switch _ch {
case string(9): {
return `\t`
}
case string(10): {
return `\n`
}
case string(13): {
return `\r`
}
case string(92): {
return `\\`
}
case `"`: {
return `\"`
}
default: {
return _ch
}
}
}
func atoms(_estr Str) Strs {
_estrs := []string{}
_chars := []string{}
_depth := 0
_mode := false
for _, _ch := range to_chars(_estr) {
if _depth == 0 {
if _ch == string(3) {
_depth += 1
}
} else if _depth == 1 {
switch _ch {
case string(3): {
_depth += 1
if _mode {
_estrs = append(_estrs, to_str(_chars))
_chars = []string{}
}
_mode = true
_chars = append(_chars, _ch)
}
case string(5): {
if _mode {
_estrs = append(_estrs, to_str(_chars))
_chars = []string{}
}
_mode = true
}
case string(4): {
if _mode {
_estrs = append(_estrs, to_str(_chars))
}
}
default: {
if _mode {
_chars = append(_chars, _ch)
}
}
}
} else {
if _ch == string(3) {
_depth += 1
}
if _ch == string(4) {
_depth -= 1
}
_chars = append(_chars, _ch)
}
}
return _estrs
}
func flat(_estr Str) (Str,Str) {
if is_str(_estr) {
println(sprintf("flat str: %s", _estr))
}
_atoms := atoms(_estr)
return _atoms[0], _atoms[1]
}
func match(_estr Str) (Str,Str) {
_atoms := atoms(_estr)
return _atoms[0], estr_strs(rest(_atoms))
}
func name(_estr Str) Str {
_chars := []string{}
_str := _estr[2:]
for _, _char := range to_chars(_str) {
if ord(_char) > 5 {
_chars = append(_chars, _char)
} else {
return to_str(_chars)
}
}
return to_str(_chars)
}
func value(_estr Str) Str {
_atoms := atoms(_estr)
return _atoms[1]
}
func elen(_estr Str) Int {
_atoms := atoms(_estr)
return len(_atoms)
}
func efirst(_estr Str) Str {
return first(atoms(_estr))
}
func epush(_estr Str,_elem Str) Str {
return add(chop(_estr), _elem, string(4))
}
func eappend(_a_one Str,_a_two Str) Str {
return add(chop(_a_one), rest_str(_a_two))
}
func eunshift(_elem Str,_array Str) Str {
return add(string(3), _elem, rest_str(_array))
}
func is_atom_name(_atom Str,_name Str) Bool {
if is_atom(_atom) {
return name(_atom) == _name
}
return false
}
func clean_ast(_ast Str) Str {
if is_atom(_ast) {
return clean_atom(_ast)
}
_clean_atoms := []string{}
for _, _atom := range atoms(_ast) {
_clean_atoms = append(_clean_atoms, clean_atom(_atom))
}
return estr_strs(_clean_atoms)
}
func clean_atom(_atom Str) Str {
_name, _value := flat(_atom)
if is_str(_value) {
return estr(_name, _value)
}
if is_blank(_value) {
return estr(_name, _value)
}
if is_atom(_value) {
return estr(_name, clean_atom(_value))
}
return estr(_name, clean_ast(_value))
}
func get_spp_ast() Str {
return `[["door",["Rules",[["Rept",["+",["Branch",[["Rept",["+",["Cclass","s"]]],["Rtoken","_comm"],["Ntoken","Spec"]]]]],["Blank"," "],["Assert","$"]]]],["_comm",["Rules",[["Char","#"],["Till",["Assert","$$"]]]]],["Spec",["Rules",[["Ntoken","Token"],["Blank"," "],["Str","->"],["Blank"," "],["Ctoken","rule"]]]],["rule",["Rules",[["Rept",["+",["Branch",[["Ntoken","Blank"],["Ntoken","Branch"],["Ctoken","atom"]]]]],["Branch",[["Cclass","v"],["Assert","$"]]]]]],["Blank",["Rept",["+",["Cclass","h"]]]],["atom",["Branch",[["Ntoken","Group"],["Ntoken","Token"],["Ntoken","Str"],["Ntoken","String"],["Ntoken","Kstr"],["Ntoken","Cclass"],["Ntoken","Char"],["Ntoken","Chclass"],["Ntoken","Assert"],["Ntoken","Any"],["Ntoken","Rept"],["Ntoken","Till"]]]],["Branch",["Rules",[["Char","|"],["Blank"," "],["Rept",["+",["Branch",[["Rept",["+",["Cclass","s"]]],["Rtoken","_comm"],["Ctoken","atom"]]]]],["Blank"," "],["Char","|"]]]],["Group",["Rules",[["Char","{"],["Blank"," "],["Rept",["+",["Branch",[["Rept",["+",["Cclass","s"]]],["Rtoken","_comm"],["Ntoken","Branch"],["Ctoken","atom"]]]]],["Blank"," "],["Char","}"]]]],["Token",["Rept",["+",["Chclass",[["Cclass","a"],["Cchar","-"]]]]]],["Kstr",["Rules",[["Char",":"],["Rept",["+",["Chclass",[["Cclass","a"],["Cchar","-"]]]]]]]],["Str",["Rules",[["Char","'"],["Rept",["+",["Branch",[["Rept",["+",["Nclass",[["Cchar","\\"],["Cchar","'"]]]]],["Group",[["Char","\\"],["Any","."]]]]]]],["Char","'"]]]],["String",["Rules",[["Char","\""],["Rept",["+",["Branch",[["Rept",["+",["Nclass",[["Cchar","\\"],["Cchar","\""]]]]],["Group",[["Char","\\"],["Any","."]]]]]]],["Char","\""]]]],["Cclass",["Rules",[["Char","\\"],["Chclass",[["Cchar","a"],["Cchar","d"],["Cchar","h"],["Cchar","l"],["Cchar","n"],["Cchar","r"],["Cchar","s"],["Cchar","t"],["Cchar","u"],["Cchar","v"],["Cchar","w"],["Cchar","x"]]]]]],["Char",["Rules",[["Char","\\"],["Any","."]]]],["Chclass",["Rules",[["Char","["],["Blank"," "],["Rept",["?",["Ntoken","Flip"]]],["Rept",["+",["Branch",[["Cclass","s"],["Ntoken","Cclass"],["Ntoken","Char"],["Ntoken","Range"],["Ntoken","Cchar"]]]]],["Blank"," "],["Char","]"]]]],["Flip",["Char","^"]],["Range",["Rules",[["Cclass","w"],["Char","-"],["Cclass","w"]]]],["Cchar",["Nclass",[["Cclass","s"],["Cchar","]"],["Cchar","#"],["Cchar","\\"]]]],["Assert",["Branch",[["Str","^^"],["Str","$$"],["Char","^"],["Char","$"]]]],["Any",["Char","."]],["Rept",["Chclass",[["Cchar","?"],["Cchar","*"],["Cchar","+"]]]],["Till",["Char","~"]]]`
}
func get_spp_grammar() Str {
return `
door -> |\s+ _comm Spec|+ $
_comm -> '#'~$$
Spec -> Token '->' rule
rule -> | Blank Branch atom |+| \v $ |
Blank -> \h+
atom -> | Group Token Str String Kstr Cclass
Char Chclass Assert Any Rept Till |
Branch -> '|' | \s+ _comm atom |+ '|'
Group -> '{' | \s+ _comm Branch atom |+ '}'
Token -> [\a\-]+
Kstr -> ':'[\a\-]+
Str -> \'| [^\\']+ {\\.} |+\'
String -> \"| [^\\"]+ {\\.} |+\"
Cclass -> \\[adhlnrstuvwx]
Char -> \\.
Chclass -> \[ Flip?|\s Cclass Char Range Cchar|+ \]
Flip -> '^'
Range -> \w'-'\w
Cchar -> [^ \s \] \# \\ ]
Assert -> | '^^' '$$' '^' '$' |
Any -> '.'
Rept -> [?*+]
Till -> '~'
`
}
func opt_spp_ast(_ast Strs) Strs {
return Map(opt_spp_atom, _ast)
}
func opt_spp_atom(_atom Str) Str {
_name, _value := flat(_atom)
switch _name {
case `Spec`: {
return opt_spp_spec(_value)
}
case `Rule`: {
return opt_spp_spec(_value)
}
case `Group`: {
return opt_spp_group(_value)
}
case `Branch`: {
return opt_spp_branch(_value)
}
case `Cclass`: {
return opt_spp_cclass(_value)
}
case `Char`: {
return opt_spp_char(_value)
}
case `Str`: {
return opt_spp_str(_value)
}
case `String`: {
return opt_spp_str(_value)
}
case `Kstr`: {
return opt_spp_kstr(_value)
}
case `Chclass`: {
return opt_spp_chclass(_value)
}
case `Token`: {
return opt_spp_token(_value)
}
case `Rept`: {
return estr(`rept`, _value)
}
default: {
return _atom
}
}
}
func opt_spp_spec(_atoms Str) Str {
_token, _rules := match(_atoms)
_name := value(_token)
_opt_rules := opt_spp_rules(_rules)
return estr(_name, _opt_rules)
}
func opt_spp_rules(_atoms Str) Str {
_opt_atoms := opt_spp_atoms(_atoms)
if len(_opt_atoms) == 1 {
return first(_opt_atoms)
}
return estr(`Rules`, estr_strs(_opt_atoms))
}
func opt_spp_group(_atoms Str) Str {
_opt_atoms := opt_spp_atoms(_atoms)
if len(_opt_atoms) == 1 {
return first(_opt_atoms)
}
return estr(`Group`, estr_strs(_opt_atoms))
}
func opt_spp_branch(_atoms Str) Str {
_opt_atoms := opt_spp_atoms(_atoms)
if len(_opt_atoms) == 1 {
return first(_opt_atoms)
}
return estr(`Branch`, estr_strs(_opt_atoms))
}
func opt_spp_atoms(_atoms Str) Strs {
return gather_spp_rept(gather_spp_till(opt_spp_ast(atoms(_atoms))))
}
func opt_spp_str(_string Str) Str {
_chars := []string{}
_mode := 0
_value := cut(_string)
for _, _char := range to_chars(_value) {
if _mode == 0 {
if _char == string(92) {
_mode = 1
} else {
_chars = append(_chars, _char)
}
} else {
_mode = 0
switch _char {
case `n`: {
_chars = append(_chars, string(10))
}
case `r`: {
_chars = append(_chars, string(13))
}
case `t`: {
_chars = append(_chars, string(9))
}
default: {
_chars = append(_chars, last_char(_char))
}
}
}
}
_str := to_str(_chars)
if len(_str) == 1 {
return estr(`Char`, _str)
}
return estr(`Str`, _str)
}
func opt_spp_kstr(_kstr Str) Str {
_str := rest_str(_kstr)
if len(_str) == 1 {
return estr(`Char`, _str)
}
return estr(`Str`, _str)
}
func opt_spp_cclass(_cclass Str) Str {
return estr(`Cclass`, last_char(_cclass))
}
func opt_spp_char(_char Str) Str {
return estr(`Char`, last_char(_char))
}
func opt_spp_chclass(_nodes Str) Str {
_atoms := []string{}
_flip := 0
for _, _node := range atoms(_nodes) {
_name, _value := flat(_node)
if _name == `Flip` {
_flip = 1
} else {
_atom := opt_spp_catom(_name, _value)
_atoms = append(_atoms, _atom)
}
}
if _flip == 0 {
return estr(`Chclass`, estr_strs(_atoms))
}
return estr(`Nclass`, estr_strs(_atoms))
}
func opt_spp_catom(_name Str,_value Str) Str {
switch _name {
case `Cclass`: {
return opt_spp_cclass(_value)
}
case `Range`: {
return opt_spp_range(_value)
}
case `Char`: {
return opt_spp_cchar(_value)
}
default: {
return estr(`Cchar`, _value)
}
}
}
func opt_spp_cchar(_char Str) Str {
return estr(`Cchar`, last_char(_char))
}
func opt_spp_range(_atom Str) Str {
return estr(`Range`, estr_strs(split(`-`, _atom)))
}
func gather_spp_till(_atoms Strs) Strs {
_opt_atoms := []string{}
_flag := 0
for _, _atom := range _atoms {
if _flag == 0 {
if is_atom_name(_atom, `Till`) {
_flag = 1
} else {
_opt_atoms = append(_opt_atoms, _atom)
}
} else {
if !is_atom_name(_atom, `Till`) {
_opt_atoms = append(_opt_atoms, estr(`Till`, _atom))
_flag = 0
}
}
}
return _opt_atoms
}
func gather_spp_rept(_atoms Strs) Strs {
_opt_atoms := []string{}
_flag := 0
_cache := ""
for _, _atom := range _atoms {
if _flag == 0 {
if !is_atom_name(_atom, `rept`) {
_cache = _atom
_flag = 1
}
} else {
if is_atom_name(_atom, `rept`) {
_rept := value(_atom)
_cache = estr(`Rept`, estr(_rept, _cache))
_opt_atoms = append(_opt_atoms, _cache)
_flag = 0
} else {
_opt_atoms = append(_opt_atoms, _cache)
_cache = _atom
}
}
}
if _flag == 1 {
_opt_atoms = append(_opt_atoms, _cache)
}
return _opt_atoms
}
func opt_spp_token(_name Str) Str {
_char := first_char(_name)
if is_upper(_char) {
return estr(`Ntoken`, _name)
}
if is_lower(_char) {
return estr(`Ctoken`, _name)
}
return estr(`Rtoken`, _name)
}
type Cursor struct {
text Str
table Table
pos Int
line Int
depth Int
capture Strs
}
func new_cursor(_str Str,_table Table) *Cursor {
_text := add(_str, string(0))
return &Cursor{
text: _text,
table: _table,
pos: 0,
line: 1,
depth: 0,
capture: []string{},
}
}
func match_table(_table Table,_text Str) Strs {
return match_door(_table, _text, `door`)
}
func match_door(_table Table,_text Str,_door Str) Strs {
_rule := _table[_door]
_c := new_cursor(_text, _table)
_match := match_spp_rule(_c, _rule)
if is_no(_match) {
fail_report(_c)
}
return _c.capture
}
func is_ok(_str Str) Bool {
return _str == string(1)
}
func is_no(_str Str) Bool {
return _str == string(2)
}
func get_char(_c *Cursor) Str {
_text := _c.text
_pos := _c.pos
return string(_text[_pos])
}
func to_next(_c *Cursor) {
_c.pos += 1
if get_char(_c) == string(10) {
_c.line += 1
}
}
func cache(_c *Cursor) Int {
return _c.pos
}
func reset_cache(_c *Cursor,_cache Int) {
_c.pos = _cache
}
func fail_report(_c *Cursor) {
_text := _c.text
_pos := _c.pos
_line := to_s(_c.line)
if len(_text) <= _pos {
error("code less ) ] }")
}
_line_str := to_end(_text, _pos)
error(sprintf("line: %s Stop match:\n%s\n^", _line,_line_str))
}
func match_spp_rule(_c *Cursor,_rule Str) Str {
_name, _value := flat(_rule)
switch _name {
case `Rules`: {
return match_spp_rules(_c, _value)
}
case `Group`: {
return match_spp_rules(_c, _value)
}
case `Branch`: {
return match_spp_branch(_c, _value)
}
case `Blank`: {
return match_spp_blank(_c)
}
case `Rept`: {
return match_spp_rept(_c, _value)
}
case `Cclass`: {
return match_spp_cclass(_c, _value)
}
case `Chclass`: {
return match_spp_chclass(_c, _value)
}
case `Nclass`: {
return match_spp_nclass(_c, _value)
}
case `Str`: {
return match_spp_str(_c, _value)
}
case `Char`: {
return match_spp_char(_c, _value)
}
case `Assert`: {
return match_spp_assert(_c, _value)
}
case `Till`: {
return match_spp_till(_c, _value)
}
case `Rtoken`: {
return match_spp_rtoken(_c, _value)
}
case `Ctoken`: {
return match_spp_ctoken(_c, _value)
}
case `Ntoken`: {
return match_spp_ntoken(_c, _value)
}
case `Any`: {
return match_spp_any(_c)
}
default: {
return string(2)
}
}
}
func match_spp_any(_c *Cursor) Str {
_char := get_char(_c)
if _char == string(0) {
return string(2)
}
to_next(_c)
return _char
}
func match_spp_assert(_c *Cursor,_assert Str) Str {
switch _assert {
case `$`: {
if get_char(_c) == string(0) {
return string(1)
}
return string(2)
}
case `$$`: {
if get_char(_c) == string(10) {
return string(1)
}
if get_char(_c) == string(0) {
return string(1)
}
return string(2)
}
default: {
error(sprintf("unknown assert: |%s|", _assert))
}
}
return string(2)
}
func match_spp_blank(_c *Cursor) Str {
for is_space(get_char(_c)) {
_c.pos += 1
}
return string(1)
}
func match_spp_rules(_c *Cursor,_rules Str) Str {
_gather := string(1)
for _, _rule := range atoms(_rules) {
_match := match_spp_rule(_c, _rule)
if is_no(_match) {
return string(2)
}
_gather = gather_spp_match(_gather, _match)
}
return _gather
}
func match_spp_branch(_c *Cursor,_branch Str) Str {
_cache := cache(_c)
for _, _rule := range atoms(_branch) {
_match := match_spp_rule(_c, _rule)
if !is_no(_match) {
return _match
}
reset_cache(_c, _cache)
}
return string(2)
}
func match_spp_ntoken(_c *Cursor,_name Str) Str {
_table := _c.table
_rule := _table[_name]
_c.depth += 1
_match := match_spp_rule(_c, _rule)
_c.depth -= 1
if is_ok(_match) {
return _match
}
if is_no(_match) {
return _match
}
_line := to_s(_c.line)
_return := name_spp_match(_name, _match, _line)
if _c.depth == 0 {
_c.capture = append(_c.capture, _return)
return string(1)
}
return _return
}
func match_spp_ctoken(_c *Cursor,_name Str) Str {
_table := _c.table
_rule := _table[_name]
return match_spp_rule(_c, _rule)
}
func match_spp_rtoken(_c *Cursor,_name Str) Str {
_ns := _c.table
_rule := _ns[_name]
_match := match_spp_rule(_c, _rule)
if is_no(_match) {
return string(2)
}
return string(1)
}
func match_spp_till(_c *Cursor,_rule Str) Str {
_buf := []string{}
_len := len(_c.text)
for _c.pos < _len {
_char := get_char(_c)
_cache := cache(_c)
_match := match_spp_rule(_c, _rule)
if !is_no(_match) {
_gather := to_str(_buf)
return gather_spp_match(_gather, _match)
}
_buf = append(_buf, _char)
reset_cache(_c, _cache)
to_next(_c)
}
return string(2)
}
func match_spp_rept(_c *Cursor,_rule Str) Str {
_gather := string(1)
_time := 0
_rept, _atom := flat(_rule)
_min, _max := get_rept_time(_rept)
for _time != _max {
_cache := cache(_c)
_match := match_spp_rule(_c, _atom)
if is_no(_match) {
if _time < _min {
return string(2)
}
reset_cache(_c, _cache)
return _gather
}
_time += 1
_gather = gather_spp_match(_gather, _match)
}
return _gather
}
func get_rept_time(_rept Str) (Int,Int) {
switch _rept {
case `?`: {
return 0, 1
}
case `*`: {
return 0, -1
}
case `+`: {
return 1, -1
}
default: {
return 0, 1
}
}
}
func match_spp_str(_c *Cursor,_str Str) Str {
for _, _char := range to_chars(_str) {
if _char != get_char(_c) {
return string(2)
}
to_next(_c)
}
return _str
}
func match_spp_char(_c *Cursor,_char Str) Str {
if _char != get_char(_c) {
return string(2)
}
to_next(_c)
return _char
}
func match_spp_chclass(_c *Cursor,_atoms Str) Str {
_char := get_char(_c)
for _, _atom := range atoms(_atoms) {
if is_match_spp_catom(_atom, _char) {
to_next(_c)
return _char
}
}
return string(2)
}
func match_spp_nclass(_c *Cursor,_atoms Str) Str {
_char := get_char(_c)
if _char == string(0) {
return string(2)
}
for _, _atom := range atoms(_atoms) {
if is_match_spp_catom(_atom, _char) {
return string(2)
}
}
to_next(_c)
return _char
}
func is_match_spp_catom(_atom Str,_char Str) Bool {
_name, _value := flat(_atom)
switch _name {
case `Range`: {
return is_match_spp_range(_value, _char)
}
case `Cclass`: {
return is_match_spp_cclass(_value, _char)
}
case `Cchar`: {
return _value == _char
}
case `Char`: {
return _value == _char
}
default: {
error(sprintf("unknown spp catom: |%s|", _name))
}
}
return false
}
func match_spp_cclass(_c *Cursor,_cclass Str) Str {
_char := get_char(_c)
if _char == string(0) {
return string(2)
}
if is_match_spp_cclass(_cclass, _char) {
to_next(_c)
return _char
}
return string(2)
}
func is_match_spp_cclass(_cchar Str,_char Str) Bool {
switch _cchar {
case `a`: {
return is_alpha(_char)
}
case `d`: {
return is_digit(_char)
}
case `h`: {
return is_hspace(_char)
}
case `l`: {
return is_lower(_char)
}
case `n`: {
return _char == string(10)
}
case `r`: {
return _char == string(13)
}
case `s`: {
return is_space(_char)
}
case `t`: {
return _char == string(9)
}
case `u`: {
return is_upper(_char)
}
case `v`: {
return is_vspace(_char)
}
case `w`: {
return is_words(_char)
}
case `x`: {
return is_xdigit(_char)
}
default: {
return false
}
}
}
func is_match_spp_range(_range Str,_char Str) Bool {
_from, _to := flat(_range)
if _from <= _char {
if _char <= _to {
return true
}
}
return false
}
func name_spp_match(_name Str,_match Str,_line Str) Str {
if is_atom(_match) {
return estr(_name, estr(_match), _line)
}
return estr(_name, _match, _line)
}
func gather_spp_match(_gather Str,_match Str) Str {
if is_ok(_match) {
return _gather
}
if is_ok(_gather) {
return _match
}
if is_str(_match) {
if is_str(_gather) {
return add(_gather, _match)
}
return _gather
}
if is_str(_gather) {
return _match
}
if is_atom(_gather) {
if is_atom(_match) {
return estr(_gather, _match)
}
return eunshift(_gather, _match)
}
if is_atom(_match) {
return epush(_gather, _match)
}
return eappend(_gather, _match)
}
func lint_spp_ast(_ast Strs) {
_table := Table{}
_values := []string{}
for _, _atom := range _ast {
_name, _value := flat(_atom)
if exists(_table, _name) {
error(sprintf("repeat define rule: |%s|", _name))
} else {
_table[_name] = `define`
_values = append(_values, _value)
}
}
if !exists(_table, `door`) {
error("Spp Ast not exist rule name: |door|")
}
for _, _rule := range _values {
lint_spp_rule(_table, _rule)
}
for _name, _ := range _table {
if _name != `door` {
_value := _table[_name]
if _value == `define` {
error(sprintf("not used rule: |%s|", _name))
}
}
}
}
func lint_spp_rule(_t Table,_rule Str) {
_name, _atoms := flat(_rule)
if !is_in(_name, []string{`Any`,`Str`,`Char`,`Cclass`,`Assert`,`Chclass`,`Nclass`,`Blank`}) {
switch _name {
case `Ctoken`: {
lint_spp_token(_t, _atoms)
}
case `Ntoken`: {
lint_spp_token(_t, _atoms)
}
case `Rtoken`: {
lint_spp_token(_t, _atoms)
}
case `Till`: {
lint_spp_rule(_t, _atoms)
}
case `Rept`: {
lint_spp_rept(_t, _atoms)
}
case `Branch`: {
lint_spp_atoms(_t, _atoms)
}
case `Group`: {
lint_spp_atoms(_t, _atoms)
}
case `Rules`: {
lint_spp_atoms(_t, _atoms)
}
default: {
error(sprintf("miss rule |%s| lint method", _name))
}
}
}
}
func lint_spp_rept(_t Table,_atoms Str) {
_value := value(_atoms)
lint_spp_rule(_t, _value)
}
func lint_spp_atoms(_t Table,_atoms Str) {
for _, _atom := range atoms(_atoms) {
lint_spp_rule(_t, _atom)
}
}
func lint_spp_token(_table Table,_name Str) {
if exists(_table, _name) {
_table[_name] = `ok`
} else {
error(sprintf("not exists rule: |%s|", _name))
}
}
func get_spp_table() Table {
_ejson := get_spp_ast()
_ast := from_ejson(_ejson)
return ast_to_table(atoms(_ast))
}
func ast_to_table(_ast Strs) Table {
_table := Table{}
for _, _spec := range _ast {
_name, _rule := flat(_spec)
_table[_name] = _rule
}
return _table
}
func grammar_to_ast(_table Table,_grammar Str) Strs {
_match := match_table(_table, _grammar)
return opt_spp_ast(_match)
}
func rule_repl() {
_table := get_spp_table()
println(`This is Spp REPL, type enter to exit.`)
for true {
print(`>> `)
_line := stdin()
_line = trim(_line)
if _line != "" {
_match := match_door(_table, _line, `rule`)
println(to_ejson(clean_ast(first(_match))))
}
}
}
func spp_repl() {
_table := get_spp_table()
println(`This is Spp REPL, type enter to exit.`)
for true {
print(`>> `)
_line := stdin()
_line = trim(_line)
if _line != "" {
_match := match_table(_table, _line)
_ast := opt_spp_ast(_match)
_clean_ast := clean_ast(first(_ast))
println(to_ejson(_clean_ast))
}
}
}
func update_spp_ast() {
_grammar := get_spp_grammar()
_table := get_spp_table()
_ast := grammar_to_ast(_table, _grammar)
lint_spp_ast(_ast)
_json := to_ejson(clean_ast(estr_strs(_ast)))
_package := `(module Spp.SppAst)`
_fn := "(fn (get-spp-ast) (return '''"
_code := add(_package, _fn, _json, "'''))")
_ast_file := `SppAst.my`
write_file(_ast_file, _code)
println(sprintf("update ok! write file %s", _ast_file))
}
func lint_spp_file(_file Str) {
_grammar := read_file(_file)
_table := get_spp_table()
_ast := grammar_to_ast(_table, _grammar)
lint_spp_ast(_ast)
}
func get_spp_parser(_grammar_file Str) Table {
_grammar := read_file(_grammar_file)
_table := get_spp_table()
_ast := grammar_to_ast(_table, _grammar)
lint_spp_ast(_ast)
return ast_to_table(_ast)
}
func parse_with_table(_table Table,_text_file Str) Str {
_text := read_file(_text_file)
_match := match_table(_table, _text)
_clean_ast := clean_ast(estr_strs(_match))
return to_ejson(_clean_ast)
}
func parse_grammar(_grammar_file Str,_text_file Str) {
_parser := get_spp_parser(_grammar_file)
println(parse_with_table(_parser, _text_file))
}
func GetArgs(_args Strs) {
_usage := `
Repl to debug Spp rule:
> go run Spp.go -rule
Repl to debug Spp grammar:
> go run spp.go -spp
Lint grammar:
> go run spp.go -lintspp grammar.file
parse text with spp grammar to Json:
> go run spp.go -parse grammar.file text.file
`
_nums := len(_args)
if _nums == 1 {
rule_repl()
} else if _nums == 2 {
_flag := _args[1]
switch _flag {
case `-rule`: {
rule_repl()
}
case `-spp`: {
spp_repl()
}
case `-help`: {
println(_usage)
}
case `-update`: {
update_spp_ast()
}
default: {
println(_usage)
}
}
} else if _nums == 3 {
_flag := _args[1]
_file := _args[2]
switch _flag {
case `-lint`: {
lint_spp_file(_file)
}
default: {
println(_usage)
}
}
} else {
_flag := _args[1]
_file := _args[2]
_tfile := _args[3]
if _flag == `-parse` {
parse_grammar(_file, _tfile)
} else {
println(_usage)
}
}
}
func main() {
GetArgs(os.Args)
}

Опубликовать ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://api.gitlife.ru/oschina-mirror/str-go-spp.git
git@api.gitlife.ru:oschina-mirror/str-go-spp.git
oschina-mirror
str-go-spp
str-go-spp
master