Scala-анализ взаимно рекурсивных функций для SML - PullRequest
4 голосов
/ 24 марта 2012

Я пытаюсь написать парсер в Scala для SML с токенами.Это почти работает так, как я хочу, чтобы это работало, за исключением того факта, что в настоящее время он анализирует

let fun fx = r и fun gy в конце r;

вместо

пусть fun fx = r и gy в конце r;

Как мне изменить мой код, чтобы он распознал, что ему не нужен FunToken для второй функции?

def parseDef:Def = {
  currentToken match {
  case ValToken => {
    eat(ValToken);

    val nme:String = currentToken match {
      case IdToken(x) => {advance; x}
      case _ => error("Expected a name after VAL.")
    }

    eat(EqualToken);      
    VAL(nme,parseExp)
    }

  case FunToken => {

    eat(FunToken);

    val fnme:String = currentToken match {
      case IdToken(x) => {advance; x}
      case _ => error("Expected a name after VAL.")
    }

    val xnme:String = currentToken match {
      case IdToken(x) => {advance; x}
      case _ => error("Expected a name after VAL.")
    }

    def parseAnd:Def = currentToken match {
      case AndToken => {eat(AndToken); FUN(fnme,xnme,parseExp,parseAnd)}
      case _ => NOFUN
    }


    FUN(fnme,xnme,parseExp,parseAnd)
    }
    case _ => error("Expected VAL or FUN.");
  }
}

Ответы [ 2 ]

1 голос
/ 31 января 2017

Просто реализуйте правильную грамматику.Вместо

def ::= "val" id "=" exp | fun
fun ::= "fun" id id "=" exp ["and" fun]

грамматика SML на самом деле равна

def ::= "val" id "=" exp | "fun" fun
fun ::= id id "=" exp ["and" fun]

Кстати, я думаю, есть другие проблемы с вашим анализом веселья.AFAICS, вы не разбираете "=" в забавном случае.Более того, после «и» вы даже не анализируете никакие идентификаторы, а просто тело функции.

0 голосов
/ 31 января 2017

Вы можете ввести FunToken обратно в ваш поток ввода с помощью функции «unsat».Это не самое элегантное решение, но оно требует наименьшего изменения вашего текущего кода.

def parseAnd:Def = currentToken match {
    case AndToken => { eat(AndToken); 
                       uneat(FunToken);
                       FUN(fnme,xnme,parseExp,parseAnd) }
  case _ => NOFUN
}
...