Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package main
- import (
- "fmt"
- "io/ioutil"
- "os"
- )
- var (
- graph = make(map[string]*Vertex)
- formal_args = make(map[string]int)
- curFunc string
- count = 1
- time = 1
- )
- type Lexeme struct {
- //Лексема
- id int // 0 - это спецсимвол , 1 - константа , 2 - идентификатор
- lex string // сама лексема
- }
- type Vertex struct {
- comp , t1 , low , args, visited int
- n string //имя функции , название вершины
- edges map[string]*Vertex //список инцидентности
- }
- type Stack []*Vertex // Структура - стек указателей на вершины, нужная для алг Тарьяна
- func pop(s Stack) (Stack, *Vertex) { //Поп() из стека
- l := len(s)
- return s[:l-1], s[l-1]
- }
- func push(s Stack , v *Vertex) Stack { return append(s, v) } // Пуш() в стек
- func parse_program(lexemes *[]Lexeme , i int) int{
- /**
- Главная функция парсинга
- */
- if i < len(*lexemes){
- i = parse_program(lexemes , parse_function(lexemes , i))
- }
- return i
- }
- func parse_function(lexemes *[]Lexeme , i int) int {
- /**
- Парсинг функции
- */
- if (*lexemes)[i].id == 2{
- curFunc = (*lexemes)[i].lex //текущая функция , глобальная переменная;
- if graph[curFunc] == nil { //Если такой функции еще не было
- graph[curFunc] = &Vertex{n : curFunc , edges: make(map[string]*Vertex), args: -1, visited: 1}
- }
- i++ //увеличиваем позицию в лексемах
- if(*lexemes)[i].lex == "(" {
- j := 0
- formal_args = make(map[string]int)
- i++
- if(*lexemes)[i].lex != ")" {
- i , j = parse_idlist(lexemes , i , j)
- if (graph[curFunc].args != -1) && (graph[curFunc].args != j) {
- /*error()*/ fmt.Print("1") ; os.Exit(0)
- } else {
- graph[curFunc].args = j
- }
- }
- }
- i++
- if(*lexemes)[i].lex == ":="{
- i++
- i = parse_expr(lexemes , i)
- if(*lexemes)[i].lex == ";" {
- i++
- return i
- } else{
- error()
- }
- } else{
- error()
- }
- } else {
- error()
- }
- return i
- }
- func parse_idlist(lexemes *[]Lexeme, i int, j int) (int, int) {
- /**
- Парсер аргументов функций
- */
- formal_args[(*lexemes)[i].lex] = 1
- i++ ; j++
- if i < len(*lexemes) {
- if (*lexemes)[i].lex == "," {
- i++ //Если запятая , то рекурсивно запускаем заново
- i, j = parse_idlist(lexemes, i, j)
- return i, j
- }
- if (*lexemes)[i].lex == ")" {
- return i, j
- }
- } else {
- error()
- }
- return 0, 0
- }
- func parse_factor(lexemes *[]Lexeme, i int) int {
- if i < len(*lexemes) {
- if (*lexemes)[i].id == 1 {
- i++
- return i
- }
- if (*lexemes)[i].id == 2 {
- i++
- if i < len(*lexemes) && (*lexemes)[i].lex == "(" {
- var j, k int
- k = i - 1
- if graph[(*lexemes)[k].lex] == nil {
- graph[(*lexemes)[k].lex] = &Vertex{n: (*lexemes)[k].lex, edges: make(map[string]*Vertex), args: -1}
- }
- i++
- i, j = parse_aal(lexemes, i , 0)
- if graph[(*lexemes)[k].lex].args != -1 {
- if graph[(*lexemes)[k].lex].args != j {
- error()
- }
- } else {
- graph[(*lexemes)[k].lex].args = j
- }
- graph[curFunc].edges[(*lexemes)[k].lex] = graph[(*lexemes)[k].lex]
- return i
- } else if formal_args[(*lexemes)[i-1].lex] == 1 {
- return i
- } else {
- error()
- }
- }
- if (*lexemes)[i].lex == "(" {
- i++
- i = parse_expr(lexemes, i)
- if (*lexemes)[i].lex == ")" {
- i++
- return i
- } else {
- error()
- }
- }
- if (*lexemes)[i].lex == "-" {
- i++
- i = parse_factor(lexemes, i)
- return i
- }
- }else{
- error()
- }
- return 0
- }
- func parse_expr(lexemes *[]Lexeme , i int) int{
- i = parse_compexpr(lexemes, i)
- if i < len(*lexemes) {
- if (*lexemes)[i].lex == "?" {
- i++
- i = parse_compexpr(lexemes, i)
- if (*lexemes)[i].lex == ":" {
- i++
- i = parse_expr(lexemes, i)
- return i
- } else {
- error()
- }
- } else {
- return i
- }
- } else {
- error()
- }
- return 0
- }
- func parse_exprlist(lexemes *[]Lexeme, i int, j int) (int, int) {
- i = parse_expr(lexemes, i)
- j += 1
- if i < len(*lexemes) {
- if (*lexemes)[i].lex == "," {
- i++
- i, j = parse_exprlist(lexemes, i, j)
- return i, j
- }
- if (*lexemes)[i].lex == ")" {
- i++
- return i, j
- }
- }else {
- error()
- }
- return 0, 0
- }
- func parse_compexpr(lexemes *[]Lexeme , i int) int{
- i = parse_arithexpr(lexemes, i)
- if i < len(*lexemes) {
- temp := false
- mas := [6]string{"=", "<>", "<", ">", "<=", ">="}
- for _ , q := range mas{
- if (*lexemes)[i].lex == q {
- temp = true
- }
- } ////1234
- if temp {
- i++
- i = parse_arithexpr(lexemes, i)
- return i
- }
- return i
- } else {
- error()
- }
- return 0
- }
- func parse_aal(lexemes *[]Lexeme , i int , j int) (int , int){
- if i < len(*lexemes) {
- if (*lexemes)[i].lex != ")" {
- i, j = parse_exprlist(lexemes, i, j)
- return i, j
- } else {
- i++
- return i, j
- }
- }else {
- error()
- }
- return 0, 0
- }
- func parse_arithexpr(lexemes *[]Lexeme, i int) int {
- return parse_arithexprx(lexemes,parse_term(lexemes, i))
- }
- func parse_term(lexemes *[]Lexeme, i int) int {
- return parse_termx(lexemes, parse_factor(lexemes, i))
- }
- func parse_termx(lexems *[]Lexeme, i int) int {
- if i < len(*lexems) {
- str := (*lexems)[i].lex
- if str == "*" || str == "/" {
- i++
- i = parse_termx(lexems, parse_factor(lexems, i)) ////1234
- }
- return i
- } else {
- error()
- }
- return 0
- }
- func parse_arithexprx(lexemes *[]Lexeme, i int) int {
- if i < len(*lexemes) {
- str := (*lexemes)[i].lex
- if str == "+" || str == "-" {
- i++
- i = parse_arithexprx(lexemes, parse_term(lexemes, i))
- }
- return i
- }else {
- error()
- }
- return 0
- }
- func visitTarjan(v *Vertex, s Stack) Stack {
- /*
- Алгоритм Тарьяна для вычсиления компонент сильной связности
- */
- v.t1 = time
- v.low = time
- time++
- s = push(s , v)
- for _, u := range v.edges {
- if u.t1 == 0 {
- s = visitTarjan(u, s)
- }
- if u.comp == 0 && v.low > u.low {
- v.low = u.low
- }
- }
- if v.t1 == v.low {
- for {
- var u *Vertex
- s, u = pop(s)
- u.comp = count
- if u == v {
- break
- }
- }
- count++
- }
- return s
- }
- func tarjan() {
- for _, v := range graph {
- v.t1 = 0
- v.comp = 0
- }
- s := make(Stack, 0) //Тарьян запуск
- for _, v := range graph {
- if v.t1 == 0 {
- visitTarjan(v, s)
- }
- }
- }
- func error(){
- fmt.Printf("%s" , "error")
- os.Exit(0)
- }
- func main() {
- var s, _= ioutil.ReadAll(os.Stdin)
- runes := []rune(string(s)) //Весь код программы в "рунах"
- lexemes := make([]Lexeme, 0) //Срез лексем
- //Лексер
- for i := 0; i < len(runes); i++ {
- var str = string(runes[i]) //строка по коду ASCII >> конкатенировать в случае := , <= , >=
- if (runes[i] > 39 && runes[i] < 48) || (runes[i] > 57 && runes[i] < 64) {
- /**
- Разбор "специальных символов" в программе
- */
- l := Lexeme{id: 0, lex: str} // новая лексема равная str
- if str == ":" || str == "<" || str == ">" {
- i++
- if runes[i] == 61 || (str == "<" && runes[i] == 62) {
- str += string(runes[i]) // конкатенация строки : составные символы
- l.lex = str // меняем лексему на новую
- } else {
- i--
- }
- }
- lexemes = append(lexemes, l) //добавляем лексему в срез лексем
- } else if runes[i] >= 48 && runes[i] <= 57{
- /**
- Разбор "констант" в программе
- */
- l := Lexeme{id: 1, lex: str} // новая лексема равная str
- i++
- //chn := false
- for runes[i] >= 48 && runes[i] <= 57 { //пока дальше идет число >> конкатенация
- str += string(runes[i])
- i++
- //chn = true
- }
- i--
- l.lex = str
- lexemes = append(lexemes , l)
- } else if (runes[i] > 64 && runes[i] < 91) || (runes[i] > 96 && runes[i] < 123) {
- /**
- Разбор "идентификаторов" в программе
- */
- l := Lexeme{id : 2 , lex : str} // новая лексема равная str
- i++
- //chn := false
- for (runes[i] > 64 && runes[i] < 91) || (runes[i] > 96 && runes[i] < 123) || (runes[i] >= 48 && runes[i] <= 57) {
- //пока дальше идет буква или число >> конкатенация
- str += string(runes[i])
- i++
- //chn = true
- }
- i--
- l.lex = str
- lexemes = append(lexemes , l)
- } else if runes[i] == 10 || runes[i] == 32 {
- // если пробел или новая строка , то продолжать
- continue
- } else {
- // если нет ожидаемого символа , выдавать ошибку
- error()
- }
- }
- parse_program(&lexemes , 0)
- tarjan()
- count -= 1
- if(count == 0 || lexemes[0].lex == "eval"){
- error()
- }
- fmt.Printf("%d\n", count)
- os.Exit(0)
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement