editorial     índice3    notícias/links               Dados dados...5    tema de capa     - Pong com Slick2D em     Java  ...
notícias/linksMozilla lança beta 4 do Firefox 4                               Windos Phone 7 já está terminado      http:/...
a tua página                   Não te esqueças, esta página pode ser tua!               http://www.revista-programar.info/...
tema de capa                                                               É fundamental que percebam este conceito, pois ...
tema de capa public static void main(String[] args)                             Circle ball; {     AppGameContainer app = ...
tema de capadeslocação para a esquerda e para baixo.                      pela direita, temos de trocar a velocidade horiz...
tema de capaRecursos   • http://dev.koonsolo.com/7/dewitters-gameloop/   • http://slick.cokeandcode.com/   • http://netbea...
a programar                                                              Formatos de dados                                ...
a programarPara os leitores mais impacientes, deixamos abaixo algumas      localizações.linhas de código que facilmente se...
a programarpor websig ou webgis, encontramos também                             • Para adicionar uma coluna de geometria n...
a programarPrecisamos também adicionar uma imagem de satélite, por            • Abrir “Attributes Table” e escrever os val...
a programarA seguir, adicionamos 4 stores, que se vão reflectir nasnossas 4 camadas como se fez no QuantumGIS.Adicionar st...
a programar                                                               Geoserver e também aos ficheiros PHP para obter ...
a programarmapa.js                                                                "http://localhost:8080/geoserver/wms",Se...
a programar 15)                                                 var arreio = format.read(req);     }));     map.addControl...
a programar onLat(),                                                                              $keys =      null,      ...
a programar                FROM %s.%s            ", $esquema, $tabela);            $result = pg_query($this->db, $sql);   ...
a programar+k=1.0 +units=m +nadgrids=@null +wktext                            Referências e Ligações Importantes+no_defs"]...
a programar                                                                 foram concebidos para escrever compiladores - ...
a programarcorremos o gcc como normal, sendo necessário linkar a libfl          INT              (0|[1-9]{DIG}*)para gerar...
a programarexpressão regular, ou seja [0-9]* faz match a zero ou mais       Este conjunto de definições não introduz nada ...
a programar                                                                  [-+*/ˆ()]               return *yytext;  %%  ...
Revista programar 25
Revista programar 25
Revista programar 25
Revista programar 25
Revista programar 25
Revista programar 25
Revista programar 25
Revista programar 25
Revista programar 25
Revista programar 25
Próximos SlideShares
Carregando em…5
×

Revista programar 25

678 visualizações

Publicada em

Publicada em: Tecnologia
0 comentários
1 gostou
Estatísticas
Notas
  • Seja o primeiro a comentar

Sem downloads
Visualizações
Visualizações totais
678
No SlideShare
0
A partir de incorporações
0
Número de incorporações
2
Ações
Compartilhamentos
0
Downloads
23
Comentários
0
Gostaram
1
Incorporações 0
Nenhuma incorporação

Nenhuma nota no slide

Revista programar 25

  1. 1. editorial índice3 notícias/links Dados dados...5 tema de capa - Pong com Slick2D em Java Com a denominada revolução da Web 2.0, a utilização que muitos davam à internet foi completamente modificada. O utilizador comum passou de um simples leitor e a programar recolector a um dos mais importantes factores na Web. Hoje é possível encontrar blogs9 - Software Livre em sobre quase todos os assuntos, que reflectem muitas vezes uma simples opinião Sistemas de Informação pessoal e não uma verdade absoluta. Geográfica20 - FLEX - Fast Lexical Analyser Todavia, mais perigoso que a existência de informação errada é a existência de25 - LUA - Linguagem de excesso de informação sobre cada um. Isto levanta a questão de para que verdadeiros Programação - Parte IV fins poderão ser utilizados os dados lá colocados. De certeza que se lembra das famosas “Perguntas Secretas”, o sistema utilizado pelos serviços de correio electrónico análise para podermos redefinir a nossa senha em caso de esquecimento. Perguntas como30 -Introdução Programação “Qual foi o meu primeiro cão?” ou “Qual é a minha cor preferida?”. Actualmente um em Visual Basic 2010 dos meios mais práticos para descobrir esses mesmos dados, é fazer uma pesquisa31 -Práticas C#: Algoritmia e pelo Hi5, Facebook e quem sabe não será fácil descobrir uma história “apaixonada” Programação Estruturada sobre a vida do seu primeiro cão? Ou então descobrir que todas as personalizações feitas às páginas são de um determinado tom de cor? Isso são dados pessoais dados, equipa PROGRAMAR apesar de muitas vezes não termos noção da real utilidade que os mesmos podem ter.coordenadoresFernando Martins Recentemente a CNPD (Comissão Nacional de Protecção de Dados) impediu a Google Portugal de recolher mais imagens para o seu serviço Street View de outras cidadeseditor portuguesas ainda não contempladas, até ser informada sobre a ferramenta utilizadaAntónio Silva para garantir a privacidade das pessoas (desfocando caras e matrículas), e que esforços está a fazer a Google para a melhorar de modo a não ser tão falível como actualmente.capa Também recentemente o director executivo «É impossível apagar o seuSérgio Alves da Google, Eric Schmidt, afirmou: “Penso que passado online e seguir em a sociedade não entende o que aconteceredacção quando tudo está disponível, publicado e frente.»André Silva gravado por todos, o tempo inteiro.” EstaAugusto Manzano questão levantou muitas críticas, principalmente por parecer defender ideiasJoão Matos contrárias à da própria Google. No contexto destas declarações um colunista do NewJoão Mares York Times escreveu: “É impossível apagar o seu passado online e seguir em frente.”Jorge Paulino No entanto Eric Schmidt ainda foi mais longe ao afirmar: “Mostre-nos 14 fotografiasMarco Afonso suas e nós vamos identificá-lo. Acha que não há 14 fotografias suas na internet?” Também após muita polémica, e trocas de acusações, no inicio deste ano lectivo 700equipa de revisão escolas vão passar a ter videovigilância instalada, mas para garantir a privacidade, aFernando Martins CNPD estabeleceu regras para a instalação das câmaras nas escolas. Não podem estarJosé Oliveira direccionadas para zonas de recreio e salas de aula, mas apenas em locais de acesso àLiliana Baptista escola e nas suas imediações.Sérgio Lopes Isto mostra sem dúvida a preocupação crescente sobre aquilo que podemos partilhar sem que amanhã nos arrependamos disso.contactorevistaprogramar Nota: A Revista PROGRAMAR, depois de um acordo com a FCA, irá disponibilizar@portugal-a-programar.org análises a algumas das publicações da FCA, nomeadamente livros directamente relacionados com a programação. O nosso intuito é criar análises rigorosas e isentaswebsite que demonstrem os pontos positivos e negativos das publicações. Estamos também awww.revista-programar.info preparar outras parcerias com o intuito de lhe trazer a si, o nosso leitor, uma melhor e maior informação.issn António Silva1647-0710 <2>
  2. 2. notícias/linksMozilla lança beta 4 do Firefox 4 Windos Phone 7 já está terminado http://www.mozilla.com/pt-PT/firefox/all-beta.html A Microsoft já terminou o Windows Phone 7, e agora Actualmente na beta 4, a Mozilla pretende lançar a só falta esperar que as operadoras terminem os pormenoresversão final do Firefox 4 até ao final de Novembro deste ano. finais para vermos smarthpones com o novo OS. A versão 4 irá trazer No Windows Phone Blog pode ler-se que a equipa do algumas Windows Phone está “entusiasmada por ter atingido o maior novidades, marco da nossa equipa interna: a disponibilização para sendo que fabrico (RTM) do Windows Phone 7". as que maissaltam é vista é a nova disposição por defeito dos O que isto significa é que o sistema operativo em si estáseparadores (em que os separadores aperecem por cima da concluído, apesar de o trabalho de integração com osbarra de endereços e dos botões) e a existência de um botão parceiros da Microsoft, tanto no campo do hardware, como“Firefox”, ao invés do habitual menu. No entanto nesta nova do software e operadoras, continuar.versão beta do Firefox também são incluídas novasfuncionalidades, como um novo modo de organização de A Microsoft diz que o Windows PHone 7 é a sua plataformatabs, e um modo de sincronização de marcadores, histórico, móvel mais testada de sempre, com quase dez milseparadores abertos, definições... dispositivos a correr testes automatizados numa base diária, e mais de meio milhão de horas de utilização. Apesar de a empresa de Redmond ainda não ter avançadoGoogle Chrome 6 Lançado com uma data para a disponibilização no mercado dos http://www.google.com/chrome smartphones com este sistema operativo, o consenso na Segundo a Google a nova versão do browser é duas Internet é que tal deverá acontecer por volta de outubro.vezes mais rápida que a anterior e foram corrigidas 17 falhasde segurança, 8 das quais eram consideradas de risco alto.IOI 2010 - International Olympiad in Informatics http://www.ioi2010.org/index.shtml http://www.dcc.fc.up.pt/oni/2010/ Infelizmente nenhum dos repersentantesportugueses nas IOI conseguiu a tão ambicionadamedalha, apesar dos esforços. Resta-nos, assim, agradecera toda a delegação portuguesa pelo seu esforço em levar onome de Portugal mais longe, e ainda com mais atençãopara os Professores Pedro Ribeiro e Pedro Guerreiro, peloseu empenho em garantir todos os anos uma delegaçãoportuguesas nas edições da IOI, apesar de todos osobstáculos com que se deparam. <3>
  3. 3. a tua página Não te esqueças, esta página pode ser tua! http://www.revista-programar.info/front/yourpage <4>
  4. 4. tema de capa É fundamental que percebam este conceito, pois é a base de qualquer jogo. Numa aplicação mais complexa, existem mais pormenores a ter em atenção, mas para este jogo, a biblioteca abstrai grande parte do essencial. Pong com Slick2D em Para começar, vamos criar um novo ficheiro em Java, importar a biblioteca Slick. Podem obter a biblioteca no site Java oficial localizado em http://slick.cokeandcode.com/. Eu vou utilizar a biblioteca no ambiente NetBeans IDE, mas não devem ter problemas com qualquer outro ambiente de desenvolvimento para Java. Para dar uso da biblioteca Slick2D vamos criar uma classe para representar o jogo. Eu, num momento de grandeNeste artigo, vamos aprender a utilizar uma simples originalidade, chamei a classe ‘Game’. Temos também debiblioteca para jogos 2D chamada Slick2D. Esta biblioteca é definir alguns métodos na nossa classe, que serão chamadosbastante simples de usar e abstrai o programador das partes pela biblioteca nos momentos apropriados.mais aborrecidas na implementação básica de um jogo, taiscomo a implementação do ciclo principal de jogo ecomunicação com o sistema operativo. package mongo; import org.newdawn.slick.*; public class Game extends BasicGame { public Game(String title) { // Para implementarVou explicar o código da minha implementação, assim como }os conceitos fundamentais no desenvolvimento de qualquerjogo. Para começar vamos estudar a estrutura fundamental public void init(GameContainer gc)de qualquer aplicação interactiva. { // Para implementarUm jogo, num nível mais abstracto, é uma aplicação que }recebe e responde a eventos. Esses eventos podem serexternos (teclas pressionadas, movimento do rato) ou public void update(GameContainerinternos (por exemplo num jogo de carros, detectar a colisão gc, int delta) {contra uma parede). Em termos de código, isto traduz-se em // Para implementaralgo semelhante a: } bool gameIsRunning = true; public void render(GameContainer gc, Graphics g) { while( gameIsRunning ) { // Para implementar update(); } render(); public static void main(String[] if( userWantsToQuit() ) args) { gameIsRunning = false; // Para implementar } } }Enquanto a varíavel que indica se o jogo está a decorrer(gameIsRunning) o ciclo while é sempre executado. Em cada A classe principal vai extender a classe BasicGame,ciclo, actualizamos o estado do jogo e desenhamos o mundo disponibilizada pela biblioteca. Esta é a estrutura base parapara ecrã. Se o utilizador entretanto fechar a janela ou qualquer jogo desenvolvido com a biblioteca Slick2D. Agoracarregar numa tecla pré-definida para o efeito, a função temos de escrever o código para iniciar a biblioteca euserWantsToQuit retorna verdadeiro, actualizamos a começar o ciclo principal de jogo.variável de saida, e o ciclo acaba. <5>
  5. 5. tema de capa public static void main(String[] args) Circle ball; { AppGameContainer app = new Rectangle paddlePlayer; AppGameContainer(new Game(title)); Rectangle paddleCPU; app.setDisplayMode(width, height, fullscreen); Para mover a bola pelo ecrã, temos de representar a sua app.setTargetFrameRate(fpslimit); velocidade. Estas quantidades são normalmente app.start(); representadas por vectores de duas dimensões. A biblioteca } Slick2D possui também uma biblioteca de matemática com estas primitivas implementadas. Vamos definir algumas variáveis para a velocidade e para armazenar as pontuaçõesEste código cria uma nova instância da aplicação e passa a obtidas por cada jogador.classe correspondente ao jogo no constructor. O títulopretendido (que queremos que apareça na janela) é passadocomo argumento do constructor da classe do jogo. Depois Vector2f ballVelocity;iniciamos a janela com a largura e algura desejada, eescolhemos se a janela vai ocupar o ecrã todo. Para finalizar, int scorePlayer;executamos o método que vai iniciar o ciclo principal do int scoreCPU;jogo. Como podem ver no código, os valores foram definidoscomo variáveis estáticas da classe, para facilitar futuras Já temos, então, tudo o que precisamos para guardar oalterações. estado de jogo. Agora falta implementar os vários métodos que ficaram em branco. Vamos começar com o método de static int width = 640; iniciação, que é chamado pela biblioteca quando o jogo é static int height = 480; iniciado. Este método tem um parâmetro do tipo static boolean fullscreen = false; GameContainer, através do qual podemos aceder a outras classes que oferecem vários serviços, como o sistema de static String title = "Mongo"; input, contexto dos gráficos 2D, sistema de som, etc. static int fpslimit = 60; public void init(GameContainer gc) { gc.getInput().enableKeyRepeat();Entretanto já temos definida a estrutura básica de umaaplicação, e se executarem a aplicação deve ser mostrada paddlePlayer = newuma janela sem conteúdo. Para mostrar o conteúdo temos RoundedRectangle(5, height/2, 10, 80,de implementar os métodos correspondentes ao ciclo de 3);actualização e desenho da aplicação. paddleCPU = new RoundedRectangle(width-15, height/2,Vamos então pensar como modelar o jogo do Pong. Este 10, 80, 3);jogo foi um dos primeiros video jogos e consiste numa ball = new Circle(width/2,simulação de um campo (de ténis de mesa), onde uma bola é height/2, 6);atirada de um lado para o outro. O jogo é normalmente ballVelocity = new Vector2f(-3, 1);jogado por 2 jogadores, mas a nossa versão vai também ter }uma opção onde o segundooponente é controlado pelocomputador. Neste métodos vamos ligar suporte para repetição de teclasPara representar as duas (assim enquanto uma teclaraquetes, podemos utilizar estiver pressionada, o Slick2Dimagens, mas para facilitar a envia sempre eventos de input).implementação vamos utilizar Depois iniciamos as variáveis dedois rectângulos. Para a bola, jogo declaradas anteriormente.vamos utilizar um círculo. A Os constructores das figurasbiblioteca Slick2D já recebem os tamanhos edisponibiliza estas primitivas posições na janela. As duasgeométricas. raquetas são criadas na esquerda e na direita, e depois a bola é criada no centro do ecrã, com velocidade horizontal inicial correspondente a Pong (1972) - Atari Inc. <6>
  6. 6. tema de capadeslocação para a esquerda e para baixo. pela direita, temos de trocar a velocidade horizontal e actualizar as pontuações.Depois da iniciação estar concluida, falta implementar aactualização e a renderização do jogo. if(ball.getMinX() <= 0) { ballVelocity.x = - public void render(GameContainer gc, ballVelocity.getX(); Graphics g) { scoreCPU++; g.fill(paddlePlayer); } g.fill(paddleCPU); g.fill(ball); if(ball.getMaxX() >= width) { } ballVelocity.x = - ballVelocity.getX();O código cima é muito simples e só desenha as figuras que scorePlayer++;iniciámos para representar os jogadores e a bola. Com o }código escrito até agora, o jogo já pode ser iniciado e sãodesenhadas todas as figuras do jogo. Falta então adicionar Agora em termos verticais, só temos de trocar a velocidadevida ao jogo, com a função de simulação/actualização (o na componente Y do vector da velocidade.método update). if(ball.getMinY() <= 0)O parâmetro delta é usado para que a simulação do jogo ballVelocity.y = -seja independente da velocidade de renderização. Vejam o ballVelocity.getY();link nos recursos que explica diferentes implementações degame loops. Como este jogo é muito simples, vamos ignorar if(ball.getMaxY() >= height)o delta. ballVelocity.y = - ballVelocity.getY();Primeiro vamos pensar no que pode acontecer no Pong. Se outilizador carregar nas teclas temos de mover o rectângulopara cima ou para baixo, dependendo da tecla que foi Resta detectar colisões quando a bola bate nas raquetes.pressionada. Basta trocar a velocidade na componente do X. if if(ball.intersects(paddlePlayer) || (gc.getInput().isKeyDown(Input.KEY_UP)) ball.intersects(paddleCPU)) { { ballVelocity.x = - if(paddlePlayer.getMinY() > 0) ballVelocity.getX(); } paddlePlayer.setY(paddlePlayer.getY() - 10.0f); Experimentem correr o jogo e já devem ter algo que se } else if assemelha ao jogo do Pong. Mas temos uma falha grande. A (gc.getInput().isKeyDown(Input.KEY_DOWN) raquete do oponente não é simulada pelo computador. ) { Vamos adicionar ao jogo, para podermos jogar contra o if(paddlePlayer.getMaxY() < height) computador. Na minha implementação a “inteligência artificial” é muito simples. A raquete do oponente segue paddlePlayer.setY(paddlePlayer.getY() + sempre a posição vertical da bola, tornando impossível 10.0f); vencer o computador: } float posY = ball.getCenterY()-Temos também de actualizar a posição da bola com a paddleCPU.getHeight()/2;respectiva velocidade. paddleCPU.setY(posY); ball.setLocation(ball.getX()+ballVelocit Muito simples! O algoritmo pode ser melhorado através do y.getX(), uso de números aleatórios. Experimentem modificar o jogo ball.getY()+ballVelocity.getY()); e adicionar novas funcionalidades.Agora vamos detectar as colisões que podem acontecerquando a bola bate nos limites do campo de jogo. Emtermos horizontais, se a bola sai do ecrã pela esquerda ou <7>
  7. 7. tema de capaRecursos • http://dev.koonsolo.com/7/dewitters-gameloop/ • http://slick.cokeandcode.com/ • http://netbeans.org/ • http://slick.cokeandcode.com/wiki/doku.php João Matos, também conhecido por triton, frequenta o segundo ano do curso de Engenharia Informática e Computadores no IST. Tem como principais interesses as áreas de Sistemas Operativos, Computação Gráfica e Arquitectura de Computadores. João Matos <8>
  8. 8. a programar Formatos de dados Pouco a pouco vamos introduzindo conceitos básicos usados em SIG, como é o caso dos 2 tipos de dados básicos: Vector e Raster. Software Livre em Sistemas • Vector - Normalmente estruturado numa lista de de Informação Geográfica vértices, e como consequência o consumo de memoria virtual ao processar, bem como o espaço necessário ao armazenar, é reduzido. • Raster - Refere-se a um varrimento de uma área que depois é estruturada numa matriz. Ao contrário do vector, esta estrutura aumenta consideravelmente o consumo deIntrodução memória virtual ao processar, bem como o espaço necessário ao armazenar. • Representação de Vectores e Raster - Tanto vectoresUm Sistema de Informação Geográfica é a aplicação da área como rasters são necessariamente armazenados eminterdisciplinar Ciência da Informação Geográfica, de modo ficheiros ou bases de dados. Segue-se uma breve descriçãoem que cruza, trata e analisa informação produzida por sobre os formatos de ficheiros mais usados:várias áreas tais como: Geografia, Cartografia, Detecção • KML / KMZ - formato usado para apresentarRemota (informação obtida por satélite), Topografia, dados geográficos;Fotogrametria, ordenamento do território, gestão de • GPX - formato de dados XML para representarcatástrofes naturais e sistemas de navegação[1]. dados de GPS; • GML - formato de dados XML para exprimir características geográficas.Sistemas de Coordenadas e Projecções[2] • WKT - é uma linguagem de texto paraAntes de avançar mais concretamente para o tema central representar geometrias, sistemas de referência espacial edeste artigo, temos de falar um pouco sobre um conceito transformações entre sistemas de referência espacial. Usadoessencial em SIG: coordenada. Não é do âmbito deste artigo essencialmente em bases de dados.mergulhar nesta matéria - até porque entramos no domínio • GeoJSON - formato para codificar estruturas deda matemática / física e não é isso que se pretende - mas é dados geográficas.importante deixar o leitor consciente de que existem vários • Geotiff - formato baseado no Tiff parasistemas de coordenadas, bem com várias projecções e a intercâmbio de dados raster contendo dados geográficos.conversão entre sistemas de coordenadas e projecções é • JPG, PNG e GIF - tipos de ficheiros de imagemuma constante no dia-a-dia do profissional que trabalha sem dados geográficos.nestas matérias. Como é lógico, hoje em dia, nenhum destes • SVG - também baseado no XML, serve paracálculos matemáticos se fazem manualmente e por isso descrever de forma vectorial desenhos e gráficosexistem várias ferramentas que realizam estes cálculos. bidimensionais. • EPS - desenvolvido pela Adobe, formato digitalO sistema de coordenadas mais conhecido é o UTM - para imagens.Universal Transverse Mercator - que serve para indicarposições absolutas no globo terrestre. Neste sistemaexistem 3 coordenadas: Latitude, Longitude e Altitude - oúltimo é desprezível em contexto de duas dimensões. Caminho mais rápido mas limitado A boa notícia: existe um caminho rápido para atingir comoUm dos serviços online que podemos usar para efectuar objectivo a disponibilização de informação geográficaconversão de coordenadas entre diferentes projecções pode através de um mapa. Como todos nós já vimos, existem naser encontrado no web site Internet ferramentas ou plataformas completas quehttp://www.faunalia.pt/conversao. suportam operações comuns em Sistemas de Informação Geográfica, nomeadamente o Google Maps, da Google. EstaContudo, ao trabalhar com dados em massa, por exemplo plataforma vêm acompanhada de uma API que permite aum mapa com milhares de pontos, não é viável converter qualquer utilizador, mesmo sem experiência emcoordenadas em vários ficheiros desta forma e por isso, uma desenvolvimento de aplicações SIG, criar o seu própriodas bibliotecas - talvez a mais importante - que utiliza mapa, personalizá-lo e partilhá-lo no seu website, bastandométodos de conversão e que facilmente se integra em para isso copiar alguns exemplos documentados na própriaqualquer aplicação FOSS, é a PROJ.4[3] API da Google Maps. <9>
  9. 9. a programarPara os leitores mais impacientes, deixamos abaixo algumas localizações.linhas de código que facilmente se integram numa páginaHTML e que permitem a visualização de um mapa Contudo, para uma organização que detêm muitaacompanhado de ferramentas de navegação. informação própria em suporte de base de dados, centenas de ficheiros raster e shape, a utilização da API do GoogleO exemplo mais simples intitulado “Hello World”[4]: Maps torna-se ineficiente para lidar com tamanha informação - para não falar da necessidade de edição de raster e vectores. Assim, surge a necessidade de usar o <!DOCTYPE html "-//W3C//DTD XHTML 1.0 próprio servidor de mapas, WMS (Web Map Service) e um Strict//EN" conjunto de ferramentas de software Livre que vamos ver a seguir. "http://www.w3.org/TR/xhtml1/DTD/xhtml1 -strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> O caminho mais lento contudo... cheio de <head> potencialidades! <meta http-equiv="content-type" content="text/html; charset=utf-8"/> Primeiro a “má” notícia - se é que se pode admitir como uma <title>Google Maps JavaScript API má notícia, uma vez que esta se verifica em qualquer Example - Tavira</title> ambiente em produção de soluções empresariais: é <script necessário um forte investimento em formação contínua src="http://maps.google.com/maps?file=a dado que no âmbito de desenvolvimento de software é pi&amp;v=2&amp;key=abcdefg&sensor=true_ muita a frequência com que surgem novas soluções. or_false" type="text/javascript"></script A boa notícia é que existe uma panóplia de software Livre - > apartir de agora será referido como FOSS (Free and Open <script type="text/javascript"> Source Software) neste artigo - “para todos os gostos”, permitindo assim qualquer profissional individual, ou function initialize() { pequena empresa, atingir objectivos que apenas estariam ao if (GBrowserIsCompatible()) { alcance de grandes empresas. var map = new GMap2(document.getElementById("map_canv Passando finalmente ao cerne da questão, apresenta-se uma as")); breve descrição de FOSS mais usado em SIG, enquadrado map.setCenter(new em 3 grande categorias: Sistemas de Gestão de Bases de GLatLng(37.148605,-7.64946), 12); Dados, Desktop e Web. map.setUIToDefault(); } Nos Sistemas de Gestão de Bases de Dados (relacionais) em } FOSS, destaca-se Postgres (incluindo a extensão geoespacial PostGIS) e MySql. Não é possível debruçar-nos neste artigo </script> sobre um estudo comparativo entre estes dois sistemas mas </head> pode-se indicar algumas leituras sobre essa matéria [5]. <body onload="initialize()" onunload="GUnload()"> Em FOSS para Desktop usado em SIG destaca-se: <div id="map_canvas" style="width: QuantumGIS [6] , Kosmo [7] , gvSIG [8] , OpenJUMP [9] e 990px; height: 600px"></div> GRASS[10]. </body> É extremamente difícil apresentar neste artigo um estudo </html> comparativo sobre os programas indicados acima, pelo que deixamos os respectivos links para que o leitor daí retire as suas próprias conclusões.A má notícia: desta forma ficamos confinados e limitados àsferramentas desta plataforma. A título de exemplo, no De qualquer forma não se pode deixar de referir que emboraGoogle Maps é possivel usar 3 tipos de mapas: alguns deles sejam redundantes em certas funcionalidades, 1. Terreno - onde se distinguem estradas, lagos, a grande valia está na forma como se complementam; o quefronteiras e reservas naturais; um não faz, o outro faz. Isto faz com que, inevitavelmente 2. Satélite - imagens fornecidas por satélite; é também num desenvolvimento extremo todos eles sejampossível activar a visualização de etiquetas. importantes. 3. Street View - vista de rua; uma visualização queproporciona um ambiente real em determinadas Em FOSS para aplicações web, ou por vezes denominado <10>
  10. 10. a programarpor websig ou webgis, encontramos também • Para adicionar uma coluna de geometria no postgrespoderosíssimas plataformas de suporte e apresentação de e para que os vários clientes desktop possam interagir com odados geoespaciais. postgres, é necessário usar a função AddGeometryColumn.Mapserver[11] - Servidor de mapas baseado em PHP; Numa janela SQL, executar:Geoserver[12] - Servidor de mapas baseado em JAVA; SELECT AddGeometryColumn(‘casestudy1,OpenLayers[13] - Plataforma em Javascript; ‘percurso’, ‘the_geom’, 27492,Mapbender[14] - Plataforma em PHP, Javascript e XML; ‘MULTILINESTRING’, 2 );Mapfish[15] - Plataforma em Python, baseada no Pylons.Combina várias frameworks Javascript, nomeadamente;OpenLayers, ExtJS e GeoExt. QuantumGISComo podemos notar, existe uma forte componente de Passando agora às aplicações Desktop, vamos construir oJavascript nestas plataformas clientes. Isto deve-se nosso mapa. Para começar, podemos interagir com a baseessencialmente ao facto de que as páginas web com mapas de dados postgres e associar uma camada (layer) à nossanão se actualizam totalmente quando o visitante interage recém nascida tabela “percurso”. No QuantumGIS, clica-secom a aplicação, recorrendo quase sempre a AJAX[16]. no botão Add Layer PostGis e obtemos a seguinte formulário:Existem ainda bibliotecas “obrigatórias” usadas por váriosambientes SIG e que sem elas não era simplesmentepossível produzir aplicações e resultados geográficos emlarga escala. As mais usadas são: Gdal/Ogr, Proj.4, Geotoolse FWTools.Em ambientes Windows, existe o pacote OSGEO4W [17] quecontém uma colecção de software (alguns indicados acima),fácil de instalar e que permite iniciar rapidamentedesenvolvimento em SIG sem que o utilizador se preocupecom dependências.Para terminar este capítulo, deve-se ainda referir que, talcomo existe a W3C[18] que especifica normas standard paratodo o desenvolvimento Web, assim existe a OGC [19] pararegular ou nomalizar todo o desenvolvimento FOSS emSistemas de Informação Geográfica.Caso de Estudo - Percurso Ciclo-turismoPostgresCriar base de dados - aproveita-se esta oportunidade parademonstrar a Interface gráfica do pgadmin, sendo estetambém um software opensource.Para este caso foi criado o seguinte: • Nova base de dados “sig_revista” • Novo esquema “casestudy1” na base de dadosindicada anteriormente. • Nova tabela “percurso” com os seguintes campos: <11>
  11. 11. a programarPrecisamos também adicionar uma imagem de satélite, por • Abrir “Attributes Table” e escrever os valores “1” eum lado para tornar o nosso mapa mais atractivo, por outro “passeio” na tabela. Terminar o modo de ediçãolado, para obter uma ideia visual sobre o posicionamentodos objectos no mapa. Clica-se em Add Layer Raster(carregar um ortofotomapa - ficheiro geotiff).Um ortofotomapa é uma fotografia aérea obtida porDetecção Remota, neste caso por Satélite.O leitor deve estar a perguntar porquê o formato GeoTIFF enão um JPEG, PNG ou GIF. A razão deve-se, como já foiexplicado acima, ao facto deste formato conterpreciosíssima informação geográfica que lhe permite seraceite como camada raster.A boa notícia é que se pode converter qualquer JPEG, PNG,ou GIF, em GeoTiff, bastando para isso adicionar umaestrutura com informação geográfica. Este processo podeser feito de várias formas, nomeadamente, usando abiblioteca Gdal/Ogr. Segue-se um screenshot do nosso mapa final trabalhado no QuantumGIS. A partir daqui, já é possível por exemplo, compor uma versão de impressão com detalhes de etiquetas indicando que significa cada objecto no nosso mapa, e por conseguinte,Vamos também adicionar vectores que representam os distribui-lo à organização do evento Ciclo-turismo. Oseixos de via do nosso local escolhido. Os eixos de via são ciclistas ficaram muito satisfeitos :)importantes porque queremos desenhar o nosso percursode Ciclo-turismo com base na rede viária do nosso local.Clica-se no botão Adicionar Layer Vector - Ficheiro com os Aplicação Web (uma entre muitasvectores dos eixos de vias de trânsito (uma shape file porexemplo). soluções possíveis)A shapefile é “a excepção à regra” neste artigo sobre FOSS,uma vez que é um formato desenvolvido pela ESRI e não é Servidor de mapas - GeoserverLivre. O servidor de mapas escolhido, sem nenhuma razão em particular, para a nossa aplicação web é o Geoserver. ComoChegando a este ponto, já temos 4 camadas no nosso mapa, alternativa, pode-se usar também o Mapserver.sendo duas delas dois raster que não estão agregados numa Considerando que o Geoserver está instalado e a correr nosó camada, ou layer. servidor, seguem-se os seguintes passos: Entrar na interface web através do endereço: http://localhost:8081/geoserverComo não se sabe que coordenadas vão traçar o nosso Fazer login como user “admin” e password “geoserver”percurso, faz-se um desenho no nosso mapa, na camadaPostGIS. Os dados a serem gravados na nossa tabelaconseguem-se com os seguintes passos: O Geoserver organiza os dados em Workspaces, Stores, • Iniciar o modo edição na layer “percurso”; Layers e Styles. • Desenhar o percurso usando o botão “Capture Line”; O primeiro passo é configurar uma workspace. <12>
  12. 12. a programarA seguir, adicionamos 4 stores, que se vão reflectir nasnossas 4 camadas como se fez no QuantumGIS.Adicionar stores: Adicionar store PostGIS. Tal como se fez para as stores anteriores mas desta feita, o Vector Data Source é PostGIS. Layers Após concluir a adição das stores, é tempo de configurar as camadas (layers) para que estejam activas e disponíveis para que o cliente web, por exemplo, OpenLayers, possa fazer a pedidos destas camadas ao Geoserver. <13>
  13. 13. a programar Geoserver e também aos ficheiros PHP para obter dados do PostGIS. • Ficheiros PHP para consultar a base de dados e devolver dados no formato JSON. É possivel com apenas um ficheiro HTML (incluido Javascript) apresentar o nosso mapa na web, no entanto, a partir desta estrutura apresentada aqui, o programador têm uma base com muito maior potencial para desenvolver esta aplicação. Outra plataforma com enorme potencial para desenvolver aplicações web em SIG é o Mapfish. Portanto asA imagem que se segue exemplifica alguns parâmetros potencialidades opensource são quase inesgotaveis.extremamente importantes aquando a configuração delayers. Se estes parâmetros não estiverem correctamente index.htmldefinidos, não será possível compor correctamente o nossomapa no lado do cliente.Todas as stores que adicionamos partilham do mesmo <!DOCTYPE html PUBLIC "-//W3C//DTDsistema de Coordenadas, identificado por “EPSG:27492”. XHTML 1.0 Transitional//EN"Esta condição de ter o mesmo sistema de coordenadas entre "http://www.w3.org/TR/xhtml1/DTD/xhtml1as layers que queremos publicar é imprescindível para que as -transitional.dtd">camadas se sobreponham correctamente. <htmlOs dados para as Bounding Boxes, se os dados estiverem xmlns="http://www.w3.org/1999/xhtml">todos com informação geográfica, bastará clicar no botão <head>“Compute from Data”. <title>Case Study - Cicloturismo</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <link rel="stylesheet" type="text/css" href="css/style.css"></link> <script src="js/prototype.js" type="text/javascript"></script> <script src="js/OpenLayers- 2.9.1/OpenLayers.js" type="text/javascript"></script> <link rel="stylesheet" type="text/css" href="js/OpenLayers- 2.9.1/theme/default/style.css"></script >Para terminar no lado do servidor, o Geoserver irá <script src="js/mapa.js"disponibilizar as camadas (layers) através do WMS, ou Web type="text/javascript"></script>Map Service. WMS é um web service que responde a pedidos </head>de clientes de mapas, nomeadamente, OpenLayers. Tal <body onload="init()">como se viu no exemplo do Google Maps, agora temos o <div id="map"></div>nosso WMS fornecido pelo nosso servidor de mapas <div id="scale"></div>Geoserver. <div id="location"></div> <p><input type="button" value="Carregar geometria da base de dados da tabela paragens"Cliente WEB onclick="return updateParagens();"></input></p>Para desenvolver o cliente da nossa aplicação, é necessário </body>ter em conta os seguintes requisitos: </html> • Plataforma OpenLayers • Plataforma Prototype • Ficheiro HTML Ficheiro base para apresentar a aplicação (19 linhas) • Ficheiro em Javascript para fazer os pedidos ao <14>
  14. 14. a programarmapa.js "http://localhost:8080/geoserver/wms",Servirá para ler os WMS do Geoserver, usando Openlayers, {bem como fazer pedidos AJAX aos ficheiros PHP para layers:consultar e devolver dados do PostGIS no formato JSON (171 revista_programar:eixos_via,linhas) transparent: true }, { var map; singleTile: false, var paragens; isBaseLayer: false } // pink tile avoidance ); OpenLayers.IMAGE_RELOAD_ATTEMPTS = 5; // make OL compute scale according to var percurso_wms = new WMS spec OpenLayers.Layer.WMS( OpenLayers.DOTS_PER_INCH = 25.4 / "Percurso", 0.28; "http://localhost:8080/geoserver/wms", { function init(){ layers: format = image/png; revista_programar:percurso, var bounds = new transparent: true OpenLayers.Bounds( }, -11050, -286200, { -8050, -284200 singleTile: false, ); isBaseLayer: false } var options = { ); controls: [], maxExtent: bounds, var paragens_wms = new restrictedExtent: bounds, OpenLayers.Layer.WMS( maxResolution: "Paragens", 11.467730468750002, "http://localhost:8080/geoserver/wms", projection: "EPSG:27492", { units: m, layers: numZoomLevels: 5 revista_programar:paragens, }; transparent: true map = new OpenLayers.Map(map, }, options); { singleTile: false, // Layer dos ortofotomapas isBaseLayer: false var ortos = new } OpenLayers.Layer.WMS( ); "Ortofotomapa", "http://localhost:8080/geoserver/wms", // create a vector layer for { drawing layers: Cicloturismo_ortos paragens = new }, OpenLayers.Layer.Vector("Paragens { Vectores"); singleTile: false, isBaseLayer: true map.addLayers([ortos, eixos_via, } percurso_wms, paragens_wms, ); paragens]); // setup tiled layer // build up all controls var eixos_via = new map.addControl(new OpenLayers.Layer.WMS( OpenLayers.Control.PanZoomBar({ "Eixos de Via", position: new OpenLayers.Pixel(2, <15>
  15. 15. a programar 15) var arreio = format.read(req); })); map.addControl(new var feature, i, j, wktfeat, OpenLayers.Control.LayerSwitcher()); geomarray, feat, geom; map.addControl(new if (reset) OpenLayers.Control.Navigation()); layer.destroyFeatures(); map.addControl(new var type = typeof arreio; OpenLayers.Control.Scale($(scale))); map.addControl(new if (arreio.length > 0) { OpenLayers.Control.MousePosition({eleme for (i = 0; i<=arreio.length - nt: $(location)})); 1; i++) { feature = arreio[i]; selectControl = new if (feature.wkt) { OpenLayers.Control.SelectFeature(parage wktfeat = ns, wktformat.read(feature.wkt); {onSelect: onFeatureSelect, type = typeof wktfeat; onUnselect: onFeatureUnselect}); map.addControl(selectControl); if (type == array) { selectControl.activate(); geomarray = []; for(j=0; j <= map.zoomToExtent(bounds); wktfeat.length - 1; j++) { map.zoomTo(1); geomarray.push( wktfeat[j].geometry); } } geom = new function updateParagens() { OpenLayers.Geometry.Collection(geomarra new y); Ajax.Request("http://localhost/revista/ } php/ajax_db_json.php", { else { method: post, geom = parameters: { wktfeat.geometry; esquema: casestudy1, } tabela: paragens }, feat = new onSuccess: function(transport) OpenLayers.Feature.Vector(geom, { feature, feature.style); var many = layer.addFeatures([feat json(transport.responseText, paragens, ], {silent: true}); true); } var s = (many > 1 ? s : } ); } alert(Foram carregada + s + return arreio.length; + many + geometria + s + da } base de dados); alert(Clique num ponto de function onPopupClose(evt) { paragem para ver mais informação); } selectControl.unselect(selectedFeature) }); ; } } function onFeatureSelect(feature) { function json(req, layer, reset) { selectedFeature = feature; popup = new var format = new OpenLayers.Popup.FramedCloud("chicken", OpenLayers.Format.JSON(); var wktformat = new OpenLayers.Format.WKT(); feature.geometry.getBounds().getCenterL <16>
  16. 16. a programar onLat(), $keys = null, array_keys($arreio); "<div style=font- //echo gettype($keys[0]); size:.8em>Detalhes da Paragem: " + if (gettype($keys[0]) == feature.attributes.nome + "</div>", integer) { null, true, onPopupClose); $result .= [; feature.popup = popup; map.addPopup(popup); foreach ($arreio as } $value) { function onFeatureUnselect(feature) { if map.removePopup(feature.popup); (gettype($value) == array) feature.popup.destroy(); $result .= feature.popup = null; $this->jsonencode($value); } else $result .= $this->jsonhelper($value);geojson.php $i++; if ($i <Class Geojson em PHP que irá ler da base de dados e count($arreio)) $result .= ,;devolver JSON. O objectivo básico deste ficheiro está }conseguido, mas pode-se melhorar as instruções de códigopara transformar numa Classe de DAO (85 linhas). $result .= ];A função jsonencode foi desenvolvida para funcionar nas }versões PHP inferiores a 5.3. Na versão PHP 5.3 é preferível else {usar a função nativa json_encode. $result .= {; foreach ($arreio as <?php $key => $value) { class Geojson { if var $db; (gettype($value) == array) function __construct() { $result .= $this->db = ".$key.":.$this- pg_connect("host=localhost port=5432 >jsonencode($value); dbname=sig_revista user=postgres else $result .= password=password"); ".$key.":.$this- } >jsonhelper($value); $i++; private function jsonhelper($value) { if ($i < if (gettype($value) == count($arreio)) $result .= ,; boolean) { } if ($value) return true; else return false; $result .= }; } } if (gettype($value) == } integer) return (int) $value; else $result = []; if (gettype($value) == double) return (float) $value; return $result; if ($value == ) return } null; return " . str_replace(/, function read($esquema, $tabela) { /, $value) . "; } $sql = sprintf(" SELECT private function jsonencode($arreio) { gid, $result = ; nome, $i = 0; ST_AsText(the_geom) as if (count($arreio)) { wkt <17>
  17. 17. a programar FROM %s.%s ", $esquema, $tabela); $result = pg_query($this->db, $sql); $array = array(); $i = 0; while ($registo = pg_fetch_assoc($result)) { $array[$i] = $registo; $i++; } //return json_encode($array); return $this- >jsonencode($array); } function write() { // Por implementar } } Avançadoajax_db_json.php Deixamos algumas dicas ao leitor, em forma de lista, paraServirá para receber o pedido HttpXmlRequest, usar a classe melhorar o case study demonstrado acima:Geojson e devolver dados no formato JSON (10 linhas). • Criar um script php para construir um ficheiro noProvavelmente pode-se melhorar a lógica entre este e o formato GPX (baseado em XML)ficheiro geojson.php, de forma a que no ficheiro • Projectar sobre o Google: colocar as layers vectoriaisgeojson.php apenas se implemente as funções da classe (percurso e paragens) sobre o WMS do GoogleDAO e neste ficheiro se converta os dados obtidos para • É necessário definir no OpenLayers a InternalJSON. Projection para 900913. • Carregar da base de dados as features já transformadas para 900913 <?php • Se na tabela spatial_ref_sys não estiver definida a entrada 900913 é necessário inserir para que o header(Cache-Control: no-cache, must- PostGIS possa fazer a conversão de coordenadas revalidate); correctamente: header(Expires: Mon, 26 Jul 1997 INSERT into spatial_ref_sys (srid, 05:00:00 GMT); auth_name, auth_srid, proj4text, srtext) header(Content-type: values ( 900913, spatialreference.org, application/json); 6, +proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 require_once(geojson.php); +k=1.0 +units=m +nadgrids=@null +wktext + n o _ d e f s , $conn = new Geojson(); PROJCS["unnamed",GEOGCS["unnamed echo $conn->read($_POST[esquema], ellipse",DATUM["unknown",SPHEROID["unnamed $_POST[tabela]); ",6378137,0]],PRIMEM["Greenwich",0],UNIT[" degree",0.0174532925199433]],PROJECTION["M ?> ercator_2SP"],PARAMETER["standard_parallel _1",0],PARAMETER["central_meridian",0],PAR AMETER["false_easting",0],PARAMETER["falseAplicação Finalizada _northing",0],UNIT["Meter",1],EXTENSION["P ROJ4","+proj=merc +a=6378137 +b=6378137Segue-se um screenshot da nossa aplicação web finalizada. +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 <18>
  18. 18. a programar+k=1.0 +units=m +nadgrids=@null +wktext Referências e Ligações Importantes+no_defs"]]); OSGeo - http://www.osgeo.org/ • Definir Spherical Mercator na layer WMS do FOSS4G - http://foss4g.org/static/index.htmlGoogle IGEO - http://www.igeo.pt/ • Vista 3D: Grass + nviz e criar vista 3D • Desastres ambientais: usar Grass para gerar possíveiszonas de inundação/incêndios florestais, com base em 1. http://www.wikipedia.org/mapas com curvas de nível e mapas do terreno. 2. http://trac.osgeo.org/proj/ • Rotas http://www.igeoe.pt/utilitarios/coordenadas/trans.aspx • Solução distribuída (PostGIS + PHP) 3. http://trac.osgeo.org/proj/ Preparar tabelas postgres e inserir percursos 4.http://code.google.com/intl/pt-alternativos no Postgres PT/apis/maps/documentation/javascript/v2/introduction.htm Preparar algoritmo, por exemplo, Dijkstra (php lou postgres) 5. http://www.scribd.com/doc/456573/Artigo-Comparacao- Script php: Gerar percursos on-the-fly, a partir de SGBDs-Geocritérios de inclusão/exclusão http://www.esteio.com.br/downloads/pdf/775-0310-DOC- • Solução Unificada - pgrouting VALI-TXT.pdf pgRouting é uma extensão do PostGIS. É uma 6. http://www.qgis.orgsolução completa cuja estrutura de dados e algoritmos 7. http://www.opengis.esoperam apenas no PostGIS, ao contrário da solução 8. http://www.gvsig.orgdistribuída que usa a estrutura do PostGIS e opera o 9. http://www.openjump.orgalgoritmo numa linguagem do servidor. 10. http://www.grass.itc.it 11. http://www.mapserver.org 12. http://geoserver.orgConclusão 13. http://openlayers.org 14. http://www.mapbender.orgEspera-se que o leitor não se assuste com a enorme 15. http://mapfish.orgvariedade de software que foi aqui apresentado, pois 1 6 . A s y n c h r o n o u s J a v a Sc r i p t a n d X M L -variedade significa também riqueza de escolha e se se http://en.wikipedia.org/wiki/Ajax_(programming)considerar-mos o número de profissionais envolvidos em 17. http://trac.osgeo.org/osgeo4w/todos estes projectos, então, só nos resta reconhecer o 18. http://www.w3.orgtrabalho, esforço e dedicação que toda a comunidade 19. http://www.opengeospatial.orginternacional mantêm. Software Livre em SIG é sem dúvidaum excelente exemplo de combinação de diferenteslinguagens de programação. A consulta às referências foi realizada em Julho de 2010. Marco Filipe Vidal Afonso, com 32 anos, é Técnico de Informática na Câmara Municipal de Tavira. Estudou durante 3 anos no curso de Engenharia Informática na Universidade de Évora. É um entusiasta pelo software livre, tem experiência no desenvolvimento de websites, aplicações web e em Sistemas de Informação Geográfica na vertente web. Como hobbies, gosta de ler livros de filosofia e de jogos de estratégia. Também faz parte das seguintes equipas de desenvolvimento: Mapas do Concelho de Tavira (http://mapas.cm- tavira.pt) e Diplomatic Wars (http://www.diplomaticwars.com) Marco Afonso <19>
  19. 19. a programar foram concebidos para escrever compiladores - yacc é um acrónimo de “yet another compiler compiler” (o “Compiler Compiler” original foi escrito em 1960 por Tony Brooker) e o lex foi desenvolvido posteriormente ao yacc, destinado a ser utilizado em seu complemento - função para a qual são utilizados ainda hoje. FLEX - Fast Lexical Vamos agora usar estas ferramentas para escrever uma calculadora simples que funcione a partir da linha de Analyser comandos. Neste primeiro artigo focar-nos-emos no flex, deixando o byacc para um segundo artigo e a versão final da calculadora para um terceiro. Começando pelo flex então, importa primeiro descrever a sua estrutura. Um ficheiro flex é constituído por 3 secções delimitadas pelo separador %%. A primeira e a terceira secção são utilizadas para inserirEsta série de artigos introduz as ferramentas Unix flex e código do utilizador, escrito em C/C++, sendo a primeirabyacc através duma abordagem prática, a implementação secção usada para as definições e #includes e a terceira paraduma calculadora simples. Os artigos assumem a as rotinas principais do utilizador. A segunda secção éfamiliaridade do leitor com C e C++, a qual será necessária utilizada para as regras do flex propriamente ditas.para seguir os exemplos. Antes de prosseguir para acalculadora no entanto, importa explicar o que são e para %%que servem o flex e o byacc. .|n putchar(*yytext); %% • Flex: o flex, da autoria de Vern Paxson, tambémconhecido como “fast lexical analyser” é um gerador de Este é um exemplo muito simples de um ficheiro flex, aanalisadores lexicais. Um analisador lexical é uma primeira e terceira secção encontram-se vazias porque nãoferramenta que permite ler uma input stream e tomar introduzimos código nosso e a segunda contém uma únicaacções quando partes dessa stream correspondem a regra que se limita a fazer output do input que o programapadrões definidos pelo programador. Estes padrões, recebe. Vamos analisar esta regra primeiro:normalmente conhecidos como expressões regulares eusados em muitas outras aplicações (grep, Visual Studio,Notepad++, etc.) tal como suportados por várias linguagens .|n putchar(*yytext);(Java, Perl, PHP, Python, Ruby, Visual Basic 6, etc.) sãofundamentais para o uso do flex e serão abordados com Uma regra em flex corresponde a uma expressão regular emais profundidade noutro artigo. uma acção. A expressão regular é um padrão ao qual o analisador lexical vai tentar encontrar correspondência na • Byacc: o berkeley yacc, da autoria de Robert Corbett, input stream. Quando encontra toma a acção associada àé um gerador de parsers. Um gerador de parsers permite regra, neste caso putchar(*yytext);. A acção é código C/C++criar uma aplicação que recebe tokens e caso estes tokens do utilizador, e pode ser uma instrução solitária como acima,conformem com a gramática especificada pelo programador ou um bloco do tipo {} ou %{ %} que ocupe várias linhas. Osão tomadas acções. Estes conceitos serão abordados com ”.|n” é uma expressão regular que basicamente aceitamais profundidade ao longo dos artigos. qualquer caractere, o ponto significa qualquer caractere excepto o n e a barra significa “ou”, logo aquela expressãoO flex e o byacc são duas das variantes das ferramentas que regular pode-se ler como “qualquer caractere excepto o ndurante décadas foram o standard dum gerador de ou o n”, portanto, tudo. O yytext é um char *, queanalisadores lexicais e dum gerador de parsers em sistemas corresponde à string à qual a expressão regular fez “match”.Unix, o lex e o yacc da AT&T, desenvolvidos nos anos 70 nos Guardando aquele ficheiro como ex1.l e correndo na shell oslaboratórios Bell por Mike Lesk e Eric Schmidt (lex) e seguintes comandos,Stephen C. Johnson (yacc). Outras variantes são GNU Bison,MKS lex e yacc e Abraxas lex e yacc. Apesar de existirem flex ex1.ldiferenças entre as variantes, elas são em muitos casos gcc -o ex1 lex.yy.c -lflnegligenciáveis na óptica do utilizador, sendo possível corrermuito do código lex directamente em flex ou outra variantesem modificações, o mesmo se verificando com código yacc obtemos um executável, ex1, que se comporta como ousado em byacc ou bison. comando cat corrido sem argumentos. Vejamos então o que se passa aqui: o comando flex ex1.l está a gerar o ficheiroAinda que tenham outros usos actualmente, historicamente lex.yy.c, um ficheiro que implementa em C osgeradores de analisadores lexicais e geradores de parsers comportamentos que descrevemos em flex. Em seguida <20>
  20. 20. a programarcorremos o gcc como normal, sendo necessário linkar a libfl INT (0|[1-9]{DIG}*)para gerar o executável. DOUBLE {MANTISSA}{EXPONENT}?O que o Flex e, como veremos, o Byacc, fazem portanto é %%traduzir um conjunto de regras simples para código C (ouC++) que as implementa, limpando e facilitando o design e {INT}|{DOUBLE} { yylval.d =gerando na maior parte dos casos código mais eficiente do strtod(yytext, NULL); return NUMBER; }que um programador faria manualmente. %% %% .|n putchar(*yytext); Estão aqui vários conceitos novos, especialmente se se não %% conhecer expressões regulares, portanto vamos abordar o problema lentamente. Antes de mais o que é um número, ou int main() mais precisamente, que representações existem para um { número? É importante definir isto para sabermos que yylex(); expressão regular devemos utilizar para lhe fazer } correspondência. Conhecendo C/C++ é fácil de reconhecer que 1, 15, 9.2e-5, 3.5, .2, 4., 6.e3 e .45E+14 são todasO código acima é idêntico ao anterior e se compilado vai representações válidas de números, portanto a nossacomportar-se da mesma forma. A diferença aqui reside na expressão regular tem que saber reconhecer todas.introdução da função main na terceira secção. Comecemos pelo mais simples, a expressão regular queAnteriormente o main não foi introduzido porque caso ele corresponde a um dígito é [0-9]. Esta sintaxe com osesteja omisso o flex linka-o automaticamente, mas importa parênteses rectos indica uma classe de caracteres emencionar que é possível escrevermos o nosso próprio main representa um intervalo de caracteres ao qual queremoscaso o desejemos. Neste caso em particular o main é igual fazer match. Se quisermos fazer match a uma letra qualquerao que o flex usa, limitando-se a chamar a função yylex(), por exemplo, podemos escrever [a-z] (ou [A-Za-z] seonde estão implementadas as regras. Caso escrevamos o quisermos maiúsculas e minúsculas).nosso main devemos lembrar-nos de chamar essa funçãopara além do nosso código ou nenhuma das regras vai É possível criar classes de caracteres para qualquer conjuntoexecutar. que nos interesse fazer match. Por exemplo se quisermos criar uma regra para apanhar vogais podemos escreverVamos agora considerar um caso mais complexo, o da nossa [aeiouAEIOU] indicando um a um os caracteres quecalculadora. O que é que precisamos que o flex faça neste pertencem ao nosso intervalo. É preciso tomar cuidado comcaso? Primeiro é preciso perceber que o ficheiro flex, o o hífen dentro duma classe de caracteres, num caso comoscanner, é a rotina de baixo nível, enquanto que o ficheiro [a-z] o hífen é açúcar sintáctico para representar osbyacc, o parser, é a de alto nível. É o parser que controla o caracteres de ‘a’ a ‘z’ e não os caracteres ‘a’, ‘-’ e ‘z’. Sescanner e o chama quando necessita de novo input. A função quiséssemos o segundo caso deveríamos escrever [-az], comdo scanner é ler a input stream, processá-la e informar o o hífen no início. Existem muitas outras nuances como estaparser do que leu. Portanto o que queremos que o nosso no uso de expressões regulares, mas não é objectivo desteficheiro flex faça é ler o input do utilizador e enviá-lo para o artigo abordá-las. Expressões regulares são um temaparser. No caso duma calculadora o input que nos interessa suficientemente vasto para merecer o seu próprio artigo, esão números, portanto queremos que o scanner tenha uma de facto, livros. Esta introdução limitar-se-á a explicar oregra deste género: significado das expressões regulares que usar sem entrar em maior detalhe. num retornaNumero(); Tendo agora uma noção do que são classes de caracteres importa perceber como fazer match a um número comEm que num corresponde a uma expressão regular que faz vários algarismos. Por exemplo o número 259. Poder-se-iamatch a números e retornaNumero() à acção que processa o pensar na expressão regular [0-9][0-9][0-9] e neste casonúmero e o envia para o scanner. O código flex que funcionaria, mas tem vários problemas. O primeiro e maisimplementa isto é o que se segue: óbvio é que esta expressão regular só faz match a números com três algarismos, o segundo e menos grave é a repetição DIG [0-9] de código. A solução do segundo é simples, basta fazer [0- MANTISSA 9]{3}, mas a solução do primeiro implica introduzir um novo ({DIG}*.{DIG}+)|({DIG}+.) conjunto de metacaracteres, ‘*’, ‘+’ e ‘?’. EXPONENT [eE][-+]?{DIG}+ O asterisco significa zero ou mais quando associado a uma <21>
  21. 21. a programarexpressão regular, ou seja [0-9]* faz match a zero ou mais Este conjunto de definições não introduz nada de novo, masalgarismos, portanto ””, “1”, “123” e “43538” são todos convém analisar cada definição para assentar conceitos.aceites por esta expressão regular. É importante mencionar EXPONENT é definido como um “e” ou “E” seguido de umque o asterisco “come” tudo o que consegue portanto um mais ou menos opcional e um ou mais dígitoos. Um INT énúmero com n algarismos consecutivos vai sempre ser um zero ou um numero de um a nove seguido de zero ouaceite por [0-9]*, independentemente do tamanho de n. mais dígitos. Um DOUBLE é uma MANTISSA seguida de um EXPONENT opcional. O comportamento do metacaractereO sinal de mais funciona de forma semelhante ao asterisco, ”|”, ou, é sempre como indicado na segunda definição, tudodiferindo no facto que significa um ou mais e não zero ou o que vem antes do ”|” ou tudo o que vem a seguir.mais, portanto no caso da expressão regular [0-9]+ osnúmeros aceites têm de ter sempre pelo menos um Tendo concluído a secção das definições vamos analisar asalgarismo. O ponto de interrogação significa zero ou um, regras, ou a regra neste caso, visto só termos uma.indicando um elemento opcional. Podemos escrever [-+]?[0-9]+ para indicar um número com sinal opcional ( “13”, ”-1” e {INT}|{DOUBLE} { yylval.d =”+324” são aceites por esta expressão regular). strtod(yytext, NULL); return NUMBER; }Um número com n algarismos pode ser então aceite pela A expressão regular neste caso é simples graças ao uso deexpressão regular [0-9]* (ou [0-9]+ caso n > 0) mas com esta definições, aceita um INT ou um DOUBLE. A acção tambémexpressão regular só serão aceites números naturais. Se é simples mas a compreensão total envolve pormenores quequisermos aceitar reais na notação descrita anteriormente só vamos ver quando começarmos a escrever o parser. Pornecessitaremos de uma expressão regular mais complexa enquanto basta saber que o yylval é uma union definida pelo(inteiros negativos e reais negativos serão tratados pelo parser onde guardamos o valor de retorno e o NUMBER éparser). Antes de começarmos a escrever essa expressão um #define que indica o tipo do retorno. O yylval.d é do tiporegular no entanto, vamos introduzir uma funcionalidade do double, mas o que o flex fez match foi a uma string,flex que vai tornar o nosso código mais legível. Uma portanto usamos a função strtod() da stdlib para converter aexpressão regular para apanhar endereços de email simples string para double antes de a enviarmos para o parser.como [-a-zA-Z0-9._%+]+@[-a-zA-Z0-9.]+.[a-zA-Z]{2,4}pode ser difícil de absorver de relance, mas é uma expressão Agora que já temos o scanner a aceitar números, falta-nosque o leitor já deverá compreender parcialmente, e quando aceitar as operações da calculadora e lidar com o restanteadquirir alguma prática, totalmente. No entanto esta input. Esta nova versão do ficheiro trata disso.expressão evidência a tendência das expressões regularespara se tornarem ilegíveis quando atingem um certo grau decomplexidade. Para evitar isso o flex permite criar %option outfile="CalculatorScanner.c"definições, DIG [0-9] define a expressão regular [0-9] comoDIG, permitindo aceder ao seu valor escrevendo {DIG}, ou %{seja, é equivalente escrever {DIG} ou [0-9]. #include "CalculatorParser.tab.h" MANTISSA ({DIG}*.{DIG}+)|({DIG}+.) void yyerror(char * err_msg) { printf("%sn", err_msg);A expressão acima também é uma definição (razão pela qual exit(1);está na primeira secção) e define MANTISSA como sendo }zero ou mais dígitos, seguidos de um ponto e de um ou maisdígitos ou um ou mais dígitos seguidos de um ponto. %}Existem dois pormenores que ainda não abordámos nestecaso, os parênteses e o ”.”. O ”.” é uma sequência de escape WS [ t]para indicarmos que queremos mesmo o caractere ponto e NL "n"|"r"|"rn"não o metacaractere ponto que indica qualquer caractere. DIG [0-9]Os parênteses são metacaracteres que servem comohabitual para agrupar itens. MANTISSA EXPONENT [eE][-+]?{DIG}+ ({DIG}*.{DIG}+)|({DIG}+.) EXPONENT [eE][-+]?{DIG}+ INT (0|[1-9]{DIG}*) DOUBLE {MANTISSA}{EXPONENT}? INT (0|[1-9]{DIG}*) DOUBLE {MANTISSA}{EXPONENT}? <22>
  22. 22. a programar [-+*/ˆ()] return *yytext; %% {INT}|{DOUBLE} { yylval.d = Esta classe de caracteres apanha todas as operações que a strtod(yytext, NULL); return NUMBER; } nossa calculadora vai realizar, somas, subtracções, multiplicações, divisões e potências, tal como parênteses [-+*/ˆ()] return *yytext; para podermos criar agrupamentos. Neste caso retornamos o caractere directamente ao parser, algo que podemos fazer {NL} return NL; sempre que o input ao qual queremos fazer match é só um {WS} ; /* ignore caractere. whitespace */ {NL} return NL; . yyerror("Unknown character"); No caso duma mudança de linha não existe nenhum valor %% que nos interesse retornar ao parser, portanto basta-nos informar o parser sobre o acontecimento. A necessidade de efectuar este retorno tornar-se-á mais óbvia quandoVejamos o que foi introduzido aqui. Na primeira linha temos discutirmos o parser.a seguinte instrução, {WS} ; /* ignore %option outfile="CalculatorScanner.c" whitespace */cujo propósito é simplesmente indicar ao flex que o nome O espaço em branco não interessa à nossa calculadora, masdo ficheiro que queremos que ele gere é queremos permitir que o utilizador o possa usar, portanto”CalculatorScanner.c” e não o default ”lex.yy.c”. Em seguida usamos uma instrução vazia como acção, causando com queabrimos um bloco de código C com ”%{”, e fechamo-lo mais o scanner o ignore.tarde com ”%}”. Podemos utilizar estes blocos parainserirmos código C/C++ como usual. Inserir código C/C++, . yyerror("Unknownincluindo comentários, fora destes blocos não vai funcionar character");como esperado a menos que todo esse código estejaindentado. Esta última regra destina-se a lidar com input inválido. A primeira consideração a tomar é que esta regra necessita de #include "CalculatorParser.tab.h" estar em último lugar porque o ponto faz match a tudo. A forma como o flex funciona é a seguinte, dado input queEste #include - que também era necessário na versão pode ser aceite por duas regras, o flex usa a que aceita maisanterior mas foi omitido por motivos de simplificação - é um input. Se as duas aceitarem a mesma quantidade o flex usa aheader criado pelo byacc e que contém a union e os que vem primeiro no ficheiro. Tomemos o seguinte caso:#defines mencionados anteriormente. A função yyerror()que se lhe segue, é uma função C normal, criada para lidar %%com erros no input. Veremos à frente como é usada. [0-9]{3} printf("número com 3 WS [ t] algarismos"); NL "n"|"r"|"rn" [0-9]* printf("número com n algarismos");Estas duas definições fazem respectivamente match a %%espaço em branco (quer sejam espaços ou tabs) e amudanças de linha (quer sejam de linux, mac ou windows).As aspas na definição NL são um metacaractere e indicam Para o input “123456” o output do scanner vai ser ”númeroque queremos fazer match exactamente ao que está lá com n algarismos” e não ”número com 3 algarismosnúmerodentro. No exemplo da expressão regular para os reais, com 3 algarismos” como seria se ele usasse a primeira regraquando usámos a expressão . para dizer que queríamos o duas vezes. A razão disto é que a segunda regra aceita maiscaractere ponto, podíamos ter usado a expressão ”.” para o do input que a primeira, como tal neste caso, é essa que omesmo efeito, tal como aqui podíamos ter usado a flex usa. Para o input “123” no entanto, o output vai serexpressão n|r|rn em vez da que usamos. ”número com 3 algarismos”, já que, aceitando as duas regras <23>

×