ESAME

data una grammatica mostrare che e riconoscibile per mezzo di

GRAMMATICA

PUMPING LEMMA PER DIMOSTRARE CHE NON E DI TIPO 3

si dimostra per mezzo della stringa in cui non e identificabile il pezzo centrale per effettuare la scomposizione nei tre pezzi in quanto il pezzo centrale ripetuto non e in grado di generare le due parti della stringa

si vedeva subito anche dal fatto che la prima regola di produzione presenta self embedding e il corrispondente automa a stati finiti avrebbe avuto infiniti stati

CALCOLO DEI DIRECTOR SYMBOLS SET

  • aggiungere una regola di ricorsione sinistra e mostrare che la grammatica non e più

si ha un conflitto nei director symbol set che riguardano il metasimbolo dato che si ha non disgiunto con la grammatica non e

mostrare che la ricorsione sinistra si può rimuovere ma si ottiene una grammatica diversa

RIMOZIONE DELLA RICORSIONE SINISTRA

La ricorsione sinistra e rimovibile ma si ottiene una grammatica diversa, non ottimale in caso si voglia applicare una semantica

tentare l’approccio con analisi e per verificare se si può mantenere la ricorsione sinistra senza modificare il linguaggio

CALCOLO DEI CONTESTI SINISTRI

CALCOLO DEI CONTESTI LR(0)

La grammatica in questione non risulta essere lr(0) in quanto la regola di produzione genera un conflitto shift/reduce nell’automa

per essere non devono esserci ricorsioni destre del tipo ne produzioni dello stesso metasimbolo che iniziano con la stessa forma di frase e si differiscono per un terminale , neanche le produzioni della forma sono corrette in quanto generano nel automa conflitti shift/reduce per via dell -mossa

CALCOLO DEGLI INSIEMI

e i conseguenti contesti

La grammatica risulta essere

COSTRUTTO lesect

costrutto per eseguire una data azione su tutti gli elementi di un array uguali a un dato target

lesect(oggetto_da_iterare,target){funzione da svolgere sull'oggetto}

SCALA

def lesect[T](a:Iterable[T],t:T)(expr:(T) =>Unit):Unit={
	if (!a.isEmpty){
		if (a.head == t) expr(a.head)
		lesect(a.drop(1),t)(expr)
	}
}
//il chiamante puo sfruttare la block like sintax e il costrutto e completato
val a=Array("a","b","b")
lesect(a,"b"){print}

JAVASCRIPT

function lesect(iterable,target){
  return function(expr){
    if (iterable.length!==0){
      if (iterable[0] === target){expr(iterable[0])}
      lesect(iterable.slice(1),target)(expr)
    }
  }
}
 
var a=Array("a","b","b")
lesect(a,"a")(console.log)
lesect(a,"b")(console.log)
lesect(a,"c")(console.log)

IL CACCIAVITE DEL SISTEMISTA (grep DEI POVERI)

con il potentissimo costrutto lesect e la possibilità offerta da javascript di costruire funzioni dinamicamente si possono ricreare molti tool unix semplicemente modificando un file,

const readline = require('readline');
const lesect = require('./lesect.js')
const fs = require('node:fs');
 
// check sui parametri
if (process.argv.length<4){console.error("wrong parameters"); process.exit(1)}
 
try {
  var commandfile=process.argv[2]
  var target=process.argv[3]
  const commandBody = fs.readFileSync(commandfile, 'utf8');
  var commmand= Function("x",file)
  var lines = [];
  
  var rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout,
    terminal:false
  });
 
  rl.on('line', (line) => {
    lines.push(line);
  });
  // approssimazione pessima, in questo modo non si consuma input prima di averne concluso la lettura, crash assicurato
  rl.on('close', (line) => {
    lesect(lines,target)(command)
  });
 
} catch (err) {
  process.exit(1)
}

e cosi possibile cambiare la semantica del costrutto lesect a runtime per mezzo di un semplice file javascript

  • con questo lesect emula grep
console.log
  • con questo emula il comando replace di sed
console.log(x.replace(process.argv[3],process.argv[4]))

esempi di chiamate

echo -e "a\nb\nb" | node mktool.js poorgrep.txt b
echo -e "a\nb\nb" | node mktool.js poorsed.txt a c

TRATTI DI SCALA: LE REVERSE PIPES

mostrare come scala risolve il problema dell’ereditarietà multipla per mezzo dei tratti, e le limitazioni dei tratti parametrici

// GIRA SOLO SU SCALA 3, TESTARE QUI https://scastie.scala-lang.org
class Pipe(var input:String){
	def run():Unit={
		print(input)
	}
}
trait grep(regex:String) extends Pipe{
  override def run():Unit={
    input= input.split("\\\\n").filter((x)=>{x.contains(regex)}).toList.mkString("\n");
    super.run();
  }
}
trait sed(regex:String,replace:String) extends Pipe{
  override def run():Unit={
    input= input.split("\\\\n").toList.map(x => x.replaceAll(regex,replace)).mkString("\n");
    super.run();
  }
}
(new Pipe("hello world")  with grep("pippo") with sed("hello","pippo") ).run()

non e possibile creare reverse pipes con comandi ripetutu perche perche un tratto parametrico se esteso due volte con parametro non puo essere linearizzato

class PipeGrepSed extends Pipe("Hello world") with grep("pippo") with sed("hello","pippo")
class PipeGrepSedGrep extends PipeGrepSed with grep("world")

questo non compila perche la seconda classe cerca di richiamare il costruttore del tratto grep() che viene già chiamato dalla classe padre