Example #1
0
func (pp *__arg_parserparser) _parse_alt(first _arg_parser) _arg_parser {
	switch pp.ch { //make sure next is kosher
	case _alt, _cseq, _eot, _eoi, _star, _plus, _maybe:
		gelo.SyntaxError("Illegal prefix:", pp.spec[pp.pos])
	}
	head := &_alt_parser{first, nil}
	tail := head
	for {
		if p := pp._parse1(true); p != nil {
			tail.next = &_alt_parser{p, nil}
			tail = tail.next
		} else { //_eoi
			return head
		}
		switch pp.ch {
		default:
			gelo.SyntaxError("Unexpected token",
				string(pp.spec), string(pp.spec[pp.pos-1]))
		case _alt:
			pp._next()
			switch pp.ch { //make sure next is kosher
			case _alt, _cseq, _eot, _star, _plus, _maybe:
				gelo.SyntaxError("Illegal prefix:", pp.spec[pp.pos-1])
			case _eoi:
				gelo.SyntaxError("Input ends after |")
			}
		case _cseq, _eot:
			return head
		}
		pp._next()
	}
	panic("parse alt in impossible state") //Issue 65
}
Example #2
0
func (pp *__arg_parserparser) _parse1(inalt bool) _arg_parser {
	var p _arg_parser
	for ; pp.ch == _eot; pp._next() {
	} //spin past whitespace
	switch pp.ch { //parse prefix
	default:
		gelo.SyntaxError("Unexpected token", string(pp.spec[pp.pos]))
	case _eoi:
		return nil
	case _lit:
		pp._next()
		str := pp._parse_string()
		if len(str) == 0 {
			gelo.SyntaxError("No literal after '")
		}
		pp.s[str] = true
		p = _lit_parser(str)
	case _char:
		//len >= 1, no need for check like above
		p = _var_parser(pp._parse_string())
	case _oseq:
		p = pp._parse_seq(false)
	}
	switch pp.ch {
	default:
		gelo.SyntaxError("Unexpected token", string(pp.spec[pp.pos]))
	case _star, _plus, _maybe:
		switch pp.ch {
		case _star:
			p = &_star_parser{p}
		case _plus:
			p = &_plus_parser{p}
		case _maybe:
			p = &_maybe_parser{p}
		}
		pp._next()
		switch pp.ch {
		case _char, _oseq, _star, _plus, _maybe, _lit:
			gelo.SyntaxError("Unexpected token after postfix operator")
		}
	case _alt:
		if !inalt {
			pp._next()
			p = pp._parse_alt(p)
		}
	case _eot, _eoi, _cseq: //nothing more to do

	}
	return p
}
Example #3
0
File: error.go Project: catb0t/gelo
func SyntaxError(vm *gelo.VM, args *gelo.List, ac uint) gelo.Word {
	if ac == 0 {
		gelo.ArgumentError(vm, "SyntaxError", "error-msg+", "")
	}
	//TODO should get a line-no, etc to allow creation of good error message
	gelo.SyntaxError(args)
	panic("Issue 65")
}
Example #4
0
func (pp *__arg_parserparser) _next() {
	pp.pos++
	if pp.ch == _eoi || pp.pos >= len(pp.spec) {
		pp.ch = _eoi
		return
	}
	ch := pp.spec[pp.pos]
	if int(ch) < 32 {
		gelo.SyntaxError("Illegal character in argument parser specification")
	}
	switch ch {
	case '\\':
		pp._next() //This is severly broken, what was I thinking?
		if pp.ch == _eoi {
			gelo.SyntaxError("Attempted to escape end of input")
		}
		if pp.ch != _char {
			pp.ch = _char
		}
	case ' ':
		pp.ch = _eot
	case '\'':
		pp.ch = _lit
	case '*':
		pp.ch = _star
	case '+':
		pp.ch = _plus
	case '?':
		pp.ch = _maybe
	case '|':
		pp.ch = _alt
	case '[':
		pp.ch = _oseq
	case ']':
		pp.ch = _cseq
	default:
		pp.ch = _char
	}
	if pp.ch == _char {
		pp.buf.WriteByte(ch)
	}
}
Example #5
0
func ReCon(vm *gelo.VM, args *gelo.List, ac uint) gelo.Word {
	if ac != 1 {
		gelo.ArgumentError(vm, "Re", "specification", args)
	}
	spec := vm.API.LiteralOrElse(args.Value)
	rex, err := regexp.Compile(string(spec))
	if err != nil {
		gelo.SyntaxError(vm, err.Error())
	}
	return &Regexp{rex}
}
Example #6
0
func (pp *__arg_parserparser) _parse_seq(top bool) *_seq_parser {
	var p _arg_parser
	var head, tail *_seq_parser
	for {
		pp._next()
		if p = pp._parse1(false); p != nil {
			if head != nil {
				tail.next = &_seq_parser{p, nil}
				tail = tail.next
			} else {
				head = &_seq_parser{p, nil}
				tail = head
			}
		}
		switch pp.ch {
		case _cseq:
			if top {
				gelo.SyntaxError("] before [ in argument specification")
			}
			if head == nil {
				gelo.SyntaxError("Empty argument specification")
			}
			pp._next()  //step over ]
			return head //postfix handled in _parse1
		case _eoi:
			if !top {
				gelo.SyntaxError("[ without ] in argument specification")
			}
			if head == nil {
				gelo.SyntaxError("[] empty sequence in argument specification")
			}
			return head
		}
	}
	panic("argument parser parser in impossible state") //Issue 65
}
Example #7
0
func Case_of(vm *gelo.VM, args *gelo.List, ac uint) gelo.Word {
	Args := _cases_parser(vm, args)

	key := Args["value"]
	arguments := gelo.AsList(key)
	cases, ok := vm.API.PartialEval(vm.API.QuoteOrElse(Args["cases"]))

	if !ok || cases.Next == nil && cases.Value == nil {
		gelo.SyntaxError(vm, "Expected:", _cases_parser,
			"{[value+ => resultant\n]+ [otherwise result]?} Got:", args)
	}

	//Give val a name, specified by var, in clauses of the cases block
	//XXX This disallows us from making tail calls
	if name, there := Args["var"]; there {
		if d, there := vm.Ns.DepthOf(name); there && d == 0 {
			defer vm.Ns.Set(0, name, vm.Ns.LookupOrElse(name))
		} else {
			defer vm.Ns.Del(name)
		}
		vm.Ns.Set(0, name, key)
	}

	//run val through cmd before comparing
	if cmd, there := Args["cmd"]; there {
		key = vm.API.InvokeCmdOrElse(cmd, arguments)
	}

	//Parse lines
	for ; cases != nil; cases = cases.Next {

		//if last line, see if it's the otherwise clause
		if cases.Next == nil {
			item := cases.Value.(*gelo.List)
			s, ok := item.Value.(gelo.Symbol)
			if ok && gelo.StrEqualsSym("otherwise", s) {
				if item.Next == nil || item.Next.Next != nil {
					_cases_synerr()
				}
				return _case_eval(vm, item.Next.Value, arguments)
			}
		}

		item := cases.Value.(*gelo.List)

		//line is too short
		if item.Next == nil || item.Next.Next == nil {
			_cases_synerr()
		}

		//Parse a single line
		list := extensions.ListBuilder()
		var resultant gelo.Word
		for ; item != nil; item = item.Next {
			if item.Next == nil { //ultimate cell
				resultant = item.Value
			} else if item.Next.Next == nil { //penultimate cell
				s, ok := item.Value.(gelo.Symbol)
				if ok && gelo.StrEqualsSym("=>", s) {
					continue
				}
				_cases_synerr()
			} else {
				list.Push(item.Value)
			}
		}

		//see if key matches any of the items we found on this line
		for head := list.List(); head != nil; head = head.Next {
			if key.Equals(head.Value) {
				return _case_eval(vm, resultant, arguments)
			}
		}
	}

	return gelo.Null //no match, no otherwise
}
Example #8
0
func _cases_synerr() {
	gelo.SyntaxError("Patterns needs to be:",
		"\"value+ => resultant\", where value may be a command")
}