Compiladores LEIC Alameda 2 o Semestre 2009/2010 Linguagem Pipoca Manual de Referência 22 de Março de 2010

Documentos relacionados
1.2 OPERAÇÕES BÁSICAS EM ALGORITMOS E PROGRAMAS 18

UNIVERSIDADE DO VALE DO RIO DOS SINOS - UNISINOS CENTRO DE CIÊNCIAS EXATAS E TECNOLÓGICAS - CENTRO 06. Funções, variáveis, parâmetros formais

Conteúdo programático

ISS Eletrônico. Formato de Arquivos para Transmissão de Documentos Declarados através do aplicativo OFFLINE. Extensão do Arquivo JUNHO2006.

Capítulo 1. Importação de Dados de Instituições Financeiras - Arquivo TXT 3

Aula 11: Desvios e Laços

Programação 2009/2010 MEEC - MEAer Laboratório 5 Semana de 26 de outubro de 2009

Unidade 1: O Computador

Universidade da Beira Interior Cursos: Matemática /Informática e Ensino da Informática

Questões frequentes relativas à Instrução da CMVM n.º 1/2010 Deveres de Informação dos Emitentes:

Sistemas Numéricos. Tiago Alves de Oliveira

10. CPU (Central Processor Unit) Conjunto das instruções Estrutura interna Formato das instruções...

Modelo Relacional Normalização Diagramas E-R e Tabelas Originadas

Fundamentos de Programação. Diagrama de blocos

CONTRATO DE LICENÇA DO UTILIZADOR PARA PRODUTOS DE SOFTWARE DA STONERIDGE ELECTRONICS LTD

Inteligência Artificial

Curso C: Ponteiros e Arrays

COBRANÇA BANCÁRIA CAIXA

aplicação arquivo Condições Gerais de Utilização

Linguagem de Programação C. Fluxo de Saída Padrão. Linguagem de Programação C. printf. Fluxo de Saída Padrão. Algoritmos e Lógica de Programação

Ciclo com Contador : instrução for. for de variável := expressão to. expressão do instrução

Classificação de Ativo Orçamento e Provisão de Despesa

Fundamentos de Bancos de Dados 3 a Prova Caderno de Questões

OPERAÇÕES COM FRAÇÕES

EGEA ESAPL - IPVC. Resolução de Problemas de Programação Linear, com recurso ao Excel

Manual do Revisor Oficial de Contas. Recomendação Técnica n.º 5

FATURA ELETRÔNICA DO PRESTADOR Layout do Arquivo Texto Versão 1.1.1

Modelo Comportamental

2 Segmentação de imagens e Componentes conexas

PROGRAMAÇÃO DE COMPUTADORES

SISTEMAS DIGITAIS SISTEMAS DE NUMERAÇÃO E CÓDIGOS

com Utilização do Código de Barras VERSÃO 04

D-Francoforte no Meno: Aluguer de salas de reuniões e conferências 2013/S Anúncio de concurso. Serviços

5.2.4 Análise de LCR segundo o tempo Regras de marcação LCR

Arquitecturas de Software Enunciado de Projecto

Programação de Computadores I. Linguagem C Função

O Cálculo λ sem Tipos

Lógica de Programação. Profas. Simone Campos Camargo e Janete Ferreira Biazotto

Driver Next Versão 1.0 de Português

UNIVERSIDADE DO TOCANTINS TECNOLOGIA EM ANÁLISE E DESENVOLVIMENTO DE SISTEMAS PRÁTICA EM PROGRAMAÇÃO DE SISTEMAS

GUIA PARA O PREENCHIMENTO DOS FORMULÁRIOS ENTIDADE GESTORA SOCIEDADE PONTO VERDE

Leiaute de arquivos XML para Carta-Circular 3254

Organização de Computadores 1

Manual SAGe Versão 1.2

PROPOSTA DE MECANISMO DE GESTÃO CONJUNTA DA INTERLIGAÇÃO ESPANHA-PORTUGAL

Testes de Hipóteses Estatísticas

2. OPERADORES ALGORITMOS, FLUXOGRAMAS E PROGRAMAS FUNÇÕES... 10

Módulo de Equações do Segundo Grau. Equações do Segundo Grau: Resultados Básicos. Nono Ano

Formas de Pagamento Resumida Vendas Vendedor Vendas Vendedor Resumido Vendas Vendedor Caixa Vendas por Artigos...

ELABORAÇÃO DE TRABALHOS ACADÊMICOS: NORMAS PARA APRESENTAÇÃO

Álgebra Linear Aplicada à Compressão de Imagens. Universidade de Lisboa Instituto Superior Técnico. Mestrado em Engenharia Aeroespacial

Objetivo do Portal da Gestão Escolar

Modelo Entidade Relacionamento (MER) Professor : Esp. Hiarly Alves

Programar. Visual Basic 1/61

PRESTAÇÃO DE SERVIÇOS DE ASSISTÊNCIA TÉCNICA À OPERAÇÃO E ADMINISTRAÇÃO DO SISTEMA INFORMÁTICO

PLANIFICAÇÃO INTRODUÇÃO ÀS TECNOLOGIAS DE INFORMAÇÃO BLOCO I

epucc.com.br SAIBA COMO INCLUIR INFORMAÇÕES DE COLABORADORES, CENTROS DE CUSTO E RATEIO DE DESPESAS

Informática I. Aula Aula 19-20/06/06 1

Disponibilizada a rotina Vale Presente (LOJA830) no módulo Controle de Lojas (SIGALOJA), assim como já é utilizada no módulo Front Loja (SIGAFRT).

Análise de Variância (ANOVA)

1. Como fazer uma pesquisa

Procedimento Gestão Documental

PLANOS MUNICIPAIS DE EMERGÊNCIA PERGUNTAS E RESPOSTAS

Sistemas Operacionais. Sincronização: Semáforos Problema dos Leitores/Escritores

Módulo 8 Entradas Digitais 24 Vdc Monitorado. Os seguintes produtos devem ser adquiridos separadamente para possibilitar a utilização do produto:

FastCube 2.0 Programmer Manual

,QVWDODomR. Dê um duplo clique para abrir o Meu Computador. Dê um duplo clique para abrir o Painel de Controle. Para Adicionar ou Remover programas

MODELO DE DECLARAÇÃO DE RECEITAS E DESPESAS

Cap. II EVENTOS MUTUAMENTE EXCLUSIVOS E EVENTOS NÃO- EXCLUSIVOS

Árvores. ! utilizada em muitas aplicações. ! modela uma hierarquia entre elementos. ! O conceito de árvores está diretamente ligado à recursão

Microprocessadores. Memórias

Curso de Formação de Oficiais Conhecimentos Específicos ENGENHARIA DE COMPUTAÇÃO CADERNO DE QUESTÕES

Carlos de Salles Soares Neto Segundas e Quartas, 17h40 às 19h10

0.1 Introdução Conceitos básicos

ENGENHARIA DE SOFTWARE

Despacho n.º /2015. Regulamento Académico dos Cursos de Pós-Graduação não Conferentes de Grau Académico do Instituto Politécnico de Leiria (IPLeiria)

Assunto: Identificação: Versão: Folha / Nº: Leiaute-IMPORTAÇÃO-NFSe - XML DOC-IN / 12

REGIMENTO ESPECÍFICO BASQUETEBOL. Câmara Municipal de Lisboa e Juntas de Freguesia Olisipíadas 2ª edição

UNIVERSIDADE NOVA DE LISBOA Faculdade de Ciências Médicas Conselho Executivo

Introdução a C Tipos de Dados Variáveis Operadores

1 Visão Geral. 2 Instalação e Primeira Utilização. Manual de Instalação do Gold Pedido

COMO ELABORAR UM CURRÍCULO

Introdução ao. Script. Baltazar Tavares (Psycho Mantys)

CONTEÚDOS PROGRAMÁTICOS

Apêndice II Regulamentos sobre o saquê

Especificação Técnica. Gerador XML do Novo MOD 106 e respectivos anexos

Manual Remessa Bancária

Linguagens de programação

Respostas a questões das IC s sobre a Linha de Crédito PME Investe II / QREN

Algoritmia e Programação APROG. Linguagem JAVA. Básico. Nelson Freire (ISEP DEI-APROG 2012/13) 1/31

Regulamento das Bolsas PARSUK Xperience 2014

REGIMENTO INTERNO RECOMENDADO PARA O ROTARY CLUB

Sistemas Operacionais. Rodrigo Rubira Branco

Manual do Fénix. Gestão da ficha de unidade curricular (Portal de coordenador de ECTS) DSI (Versão 1.0)

MC102 Algoritmos e programação de computadores Aula 3: Variáveis

Keeper of Knowledge. Capítulo 1 Conceitos Básicos do Java

Módulo de Aprendizagem I

Anexo 1 FUNDAÇÃO MACAU. Regulamento de Atribuição da. Bolsa para Estudos sobre Macau. Artigo 1.º. Objecto

Especificação do Código de Barras para Bloquetos de Cobrança Sem Registro e Registrada no SIGCB

Transcrição:

Compiladores LEIC Alameda 2 o Semestre 2009/2010 Linguagem Pipoca Manual de Referência 22 de Março de 2010 Classificação mínima no projecto: 9,50 valores (sem arredondamentos) (40% da nota final). Fraudes na execução do projecto terão como resultado a classificação de 0 (zero) valores e consequente reprovação no ano lectivo 2009/2010, sem prejuízo de outras acções disciplinares pelos órgãos do IST. Datas: 2010/05/03 12:00 (entrega intermédia); 2010/05/31 12:00 (entrega final); 2010/06/15 2010/06/17 (teste prático). Dúvidas que não possam ser esclarecidas presencialmente ou através do material no Fénix, devem ser colocadas através de correio electrónico (ver ereço no Fénix). Advertem-se os alunos contra a utilização de fontes de informação não oficialmente associadas ao corpo docente. Correcções a que este manual esteja sujeito serão devidamente anunciadas. Este documento não descreve a linguagem formalmente, preferindo-se uma exposição intuitiva (em português). 1 Introdução A linguagem Pipoca é uma linguagem imperativa, não estruturada e fortemente tipificada. Um dos objectivos da linguagem é permitir a fácil leitura, pelo que é fortemente restritiva relativamente ao aspecto e à posição do código nas linhas (indentação). 1.1 Tipos de dados A linguagem define quatro tipos de dados manipuláveis. Números inteiros Designados por int, ocupam 4 bytes em complemento para dois, alinhados a 32 bits. Números reais Designados por real, ocupam 8 bytes em vírgula flutuante (norma IEEE 754). Cadeias de caracteres Designadas por string, são terminadas pelo carácter com o valor 0 ASCII (NULL). As contantes e literais deste tipo podem ser utilizados em atribuições, passados como argumentos de funções e em impressões, embora o valor a imprimir possa ser uma expressão conto cadeias de caracteres ou constantes que representam cadeias de caracteres (ver 8.12). Vectores Os valores inteiros e reais são considerados vectores unidimensionais, so o escalares interpretados como vectores de dimensão unitária. Os vectores são sempre homogéneos (contêm valores de um só tipo), e.g., quando um vector inclui pelo menos um valor literal real, todo os elementos do vector são reais. A omissão do tipo é possível em alguns casos (assume-se o tipo inteiro). 1.2 Verificação de tipos As operações em depem dos tipos de dados a que são aplicadas. Os tipos suportados por cada operador e a operação a realizar são indicados na definição das expressões (ver 8). 1.3 Manipulação de nomes As entidades nomeadas (ver também 2.3) correspondem a constantes, variáveis e funções. Nos pontos que se seguem, usa-se o termo entidade para as designar indiscriminadamente, usando-se listas explícitas quando a descrição for válida apenas para um subconjunto. 1

1.3.1 Espaços de nomes O espaço de nomes global é único, pelo que um nome utilizado para designar uma entidade num dado contexto não pode ser utilizado para designar outras (ainda que de natureza diferente). 1.3.2 Validade das variáveis As entidades globais (declaradas fora de qualquer função), existem do início ao fim da execução do programa. As contantes e variáveis locais a uma função existem apenas durante a sua execução, e os argumentos formais são válidos enquanto a função está activa. 1.3.3 Visibilidade dos identificadores Os identificadores estão visíveis desde a sua declaração até ao fim do seu alcance: ficheiro (globais) ou função/bloco (locais). A reutilização de um identificador num contexto inferior encobre possíveis declarações em contextos superiores. Em particular, a redeclaração de um identificador numa função encobre o global até ao fim da função. Não é possível definir funções dentro de funções. Existem algumas restrições à definição de identificadores cujos nomes coincidam com outros já utilizados (ver 6 e 6.3). 2 Convenções Lexicais Existem seis grupos de elementos lexicais (tokens): elementos da estrutura de linhas, identificadores, palavras chave, literais (constantes), operadores de expressões e delimitadores. Em cada caso, é considerada a maior sequência de caracteres que constitua um elemento lexical válido. 2.1 Estrutura de linha Um programa está dividido em linhas lógicas e uma instrução não pode ocupar mais de uma linha lógica, excepto se a instrução permitir explicitamente mudanças de linha através, por exemplo, da utilização de blocos. Uma linha lógica pode ser constituída por uma ou mais linhas físicas separadas pelo carácter de continuação. 2.1.1 Linhas físicas A terminação de uma linha física depe da convenção utilizada pelo sistema operativo de suporte utilizado. Assim, em UNIX, o carácter utilizado é o ASCII 0x0A (linefeed, \n). No Macintosh, o carácter utilizado é o ASCII 0x0D (return, \r). Em DOS/Windows, utiliza-se a sequência ASCII 0x0D 0x0A (\r\n). 2.1.2 Carácter de continuação: junção explícita de linhas Duas linhas físicas podem ser juntas numa única linha lógica através da utilização do carácter de continuação: ASCII 0x5C (backslash, \), quando utilizado como último carácter, imediatamente antes da terminação da linha física. Este processo é válido para múltiplas linhas físicas. Por exemplo: if ano > 2006 and ano <= 2010 and dia >= 1 \ and (mes = 1 or mes = 3 or mes = 5 or mes = 7 \ or mes = 8 or mes = 10 or mes = 12 and dia <= 31) \ or (mes = 4 or mes = 6 or mes = 9 or mes = 11 and dia <= 30 )\ or mes = 8 or mes = 10 or mes = 12 and dia <= 31) \ or mes = 2 and (ano = 2008 and dia <= 29 or ano <> 2008 \ and dia <= 28 ) then dia correcto\n! dia errado\n! Além da utilização descrita, o carácter de continuação pode ser utilizado em cadeias de caracteres literais, so ilegal em qualquer outro contexto. Em particular, o carácter de continuação não pode ser utilizado para permitir a continuação de tokens (identificadores, palavras chave, delimitadores, operadores, literais inteiros ou reais), nem comentários explicativos ( 2.2). 2

2.1.3 Caracteres brancos São considerados caracteres brancos aqueles que, embora servindo para separar os elementos lexicais, não representam nenhum elemento lexical. São considerados caracteres brancos: ASCII 0x20 (espaço, ) e ASCII 0x09 (tabulação, \t). Note-se que os caracteres mencionados acima, apesar de brancos, têm significado especial se aparecerem no início de uma linha lógica (ver 2.1 e 2.1.5). Analogamente, os caracteres de mudança de linha ( 2.1.1) também têm significado especial (ver também 2.1.4 e 2.1.5). 2.1.4 Linhas brancas Uma linha lógica que contenha apenas caracteres brancos ( 2.1.3) e comentários é ignorada. Neste caso não é gerado nenhum elemento lexical nem alterada a indentação. 2.1.5 Indentação Tal como mencionado em 2.1.5, os caracteres ASCII 0x20 (espaço, ) e ASCII 0x09 (tabulação, \t) não são considerados brancos no início de uma linha lógica. Neste caso, as suas cadeias determinam o nível de indentação do código. Os caracteres de tabulação são substituídos (da esquerda para a direita) por 1 (um) a 8 (oito) espaços, de tal forma que o número total de caracteres brancos até ao carácter corrente (e incluindo este) seja o múltiplo de 8 seguinte (regra utilizada pelo UNIX). O número total de espaços brancos até ao primeiro carácter não branco determina o nível de indentação da expressão. A indentação não pode continuar na linha física seguinte mediante a utilização de uma junção explícita de linhas. Assim, no máximo, o número de espaços brancos até ao primeiro carácter de continuação determina o nível de indentação, embora as linhas físicas possam ter mais de 80 caracteres. Embora os diversos níveis de indentação possam ser diferentes, o significado pode ser o mesmo (a legibilidade pode ser diferente, depo dos casos): o exemplo da esquerda é melhor que o central (comparar indentações de a e de b), mas tem o mesmo significado. O exemplo da direita está errado. OK: bom estilo OK: mau estilo Errado! max(a, b) if a > b then a b max(a, b) if a > b then a b max(a, b) if a > b then a b 2.2 Comentários Os comentários funcionam como separadores de elementos lexicais. Existem dois tipos de comentários. Explicativos Começam com a sequência # (desde que este símbolo não faça parte de uma cadeia de caracteres), e acabam no fim da linha física (ver 2.1.2). Operacionais Começam com { e terminam com } (desde que estes símbolos não façam parte de cadeias de caracteres). Podem estar aninhados e conter várias linhas físicas. Não alteram a indentação. 2.3 Identificadores Os identificadores, também designados por nomes, são iniciados por uma letra (maiúscula ou minúscula) ou um sublinhado (_). O primeiro carácter é seguido por 0 (zero) ou mais letras, dígitos ou _. O número de caracteres que constituem um identificador é ilimitado e dois nomes designam identificadores distintos se houver alteração de maiúscula para minúscula, ou vice-versa, de pelo menos um carácter. 3

2.4 Palavras chave As palavras indicadas de seguida estão reservados (palavras chave), não podo ser utilizadas como identificadores. Estas palavras têm de ser escritas exactamente como indicado. A palavra reservada goto não é utilizada pela linguagem. not and or if then while do done until break continue return goto real integer const var init extern 2.5 Literais São notações para valores constantes de alguns tipos da linguagem (não confundir com constantes, i.e., identificadores que designam elementos cujo valor não pode sofrer alterações durante a execução do programa). 2.5.1 Inteiros Um literal inteiro é um número não negativo (uma constante inteira pode, contudo, ser negativa: números negativos são construídos pela aplicação do operador menos unário (-) a um literal positivo). Os inteiros ocupam 32 bits. Um literal inteiro em decimal é constituído por uma sequência de 1 (um) ou mais dígitos decimais (dígitos de 0 a 9) em que o primeiro dígito não é um 0 (zero), excepto no caso do número 0 (zero). Neste caso, é composto apenas pelo dígito único 0 (zero) (em qualquer base de numeração). Um literal inteiro em octal começa sempre pelo dígito 0 (zero), so seguido de um ou mais dígitos de 0 a 7. Um literal inteiro em hexadecimal começa sempre pela sequência 0x, so seguido de um ou mais dígitos de 0 a 9, de a a f, ou de A a F (elementos da base hexadecimal). Se não for possível representar o literal inteiro em 32 bits, devido a um overflow, deverá ser gerado um erro lexical. 2.5.2 Reais Um literal real é representado em notação científica e ocupa 64 bits. Um literal real inclui sempre um ponto decimal e tem dígitos decimais de um dos lados (podo não ter do outro). Assim, 2. ou 2.0 representam o valor real 2 (dois), enquanto duas décimas podem ser representadas por.2 ou 0.2. Um literal real pode ainda incluir uma parte exponencial contituída pela letra E (ou e) seguida de um inteiro (positivo ou negativo). 2.5.3 Cadeias de caracteres As cadeias de caracteres começam e terminam com plicas ( ). Uma cadeia de caracteres pode conter qualquer número de caracteres, podo estes ser ASCII ou de outras normas (e.g. ISO 8859-1, entre outros), para representação de caracteres acentuados. Dentro de uma cadeia, os caracteres utilizados para iniciar ou terminar comentários (tanto { e }, como #), têm o seu valor normal, não inciando ou terminando qualquer comentário. O carácter \ é utilizado na representação de caracteres especiais de acordo com a seguinte tabela: \ seguido de ASCII 0x0A (newline) ignorado (ver junção de linhas físicas) \\ \ (backslash) \ (plica) \n ASCII 0x0A (LF, linefeed) \r ASCII 0x0D (CR, carriage return) \t ASCII 0x09 (HT, tab) \b ASCII 0x07 (BEL, bell) \ooo carácter com valor octal dado pelos dígitos ooo \xhh carácter com valor hexadecimal dado pelos dígitos hh (outras sequências) permanecem inalteradas (incluindo o carácter \) A sequência octal, especificada por ooo, pode ter 1, 2, ou 3 dígitos, com valores entre 1 e 377 (máximo representável com 8 bits). Analogamente, a sequência hexadecimal, especificada por hh, pode ter 1 ou 2 dígitos, com valores entre 1 e FF (máximo representável com 8 bits). Tal como nos inteiros, não há distinção entre maiúsculas e minúsculas nos dígitos hexadecimais. 4

2.6 Operadores de expressões São considerados operadores os seguintes elementos lexicais: - + -- ++?! @ * / % ** < <= >= > = <> := 2.7 Delimitadores Os elementos lexicais seguintes são considerados delimitadores: [ ] ( ), 3 Gramática 3.1 Gramática A gramática da linguagem pode ser resumida pelas regras abaixo. Considerou-se que os elementos em tipo fixo são literais, que os parênteses curvos agrupam elementos, que elementos alternativos são separados por uma barra vertical, que elementos opcionais estão entre parênteses rectos, que os elementos que se repetem zero ou mais vezes estão entre { e }. A barra vertical e os parênteses são elementos lexicais da linguagem quando representados em tipo fixo. ficheiro declaração { declaração } declaração constante variável função constante const identificador {, identificador } = literal {, literal } variável variável-i variável-ni variável-i init identificador := expressão variável-ni var [ tipo ] identificador tipo integer real função [ tipo ] identificador ( [ argumentos ] ) [ bloco ] argumentos [ tipo ] identificador {, [ tipo ] identificador } literal literal-atómico literal-vector literal-atómico literal-inteiro literal-real cadeia-de-caracteres literal-vector [ literal-atómico {, literal-atómico } ] instrução if expressão then instrução [ instrução ] while expressão do instrução [ instrução ] done continue [ literal-inteiro ] break [ literal-inteiro ] return bloco expressão reserva reserva [ identificador ] = expressão Foram omitidos da gramática os seguintes elementos: tipo (ver 1.1); identificador (ver 2.3); literal-inteiro (ver 2.5.1); literalreal (ver 2.5.2); cadeia-de-caracteres (ver 2.5.3); bloco (ver 7.2); e expressão (incluindo left-values, i.e., posições de memória disponíveis para escrita) (ver 8). 3.2 Ficheiros Os ficheiros são contituídos por sequências de definições. Estas definições são utilizadas quer para declarar quer para reservar espaço para guardar os valores das entidades declaradas. É possível declarar constantes ( 4.1), variáveis ( 4.2) e funções ( 6). Os ficheiros são uniformes, so o principal aquele que contiver a função principal, designada por start. 4 Declaração de Variáveis e Constantes Cada declaração permite declarar uma única variável ou constante e inclui os componentes descritos nos pontos seguintes. 5

4.1 Constantes Designadas pela palavra reservada const, indicam identificadores constantes, i.e., o valor representado não pode ser modificado. São possíveis constantes inteiras, reais e cadeias de caracteres. As cadeias de caracteres são utilizáveis apenas num conjunto limitado de situações. Como a inicialização é obrigatória, não é necessária (ou permitida) a especificação do tipo de dados (é inferido do valor). A inicialização pode ser múltipla, so usados múltiplos identificadores e valores iniciais (separados por vírgulas em ambos os casos). Os identificadores e os valores devem ser em igual número e são emparelhados. Numa expressão, caso um identificador designe uma constante escalar o seu valor deverá ser directamente substituído no código. Exemplos: const grosa := 144 const pi := 3.1415926535 const valores := [ 1, 2.4, 3.6, 5 ] const dias, horas, minutos, segundos := 7, 24, 60, 60 const mes, dias := Abril, 30 4.2 Variáveis 4.2.1 Variáveis iniciadas A definição de variáveis iniciadas começa com a palavra chave init seguida do identificador a iniciar, do operador de atribuição (embora se trate de uma inicialização) e de uma sequência de valores separados por vírgulas e delimitados por parênteses rectos (excepto para cadeias de caracteres). Tal como para as constantes, como a inicialização é obrigatória, não é necessária (ou permitida) a especificação do tipo de dados (é inferido do valor). Notar que todos os valores são considerados vectores, pelo que os escalares são vectores compostos por um só elemento. Cada instrução de iniciação só inicia uma variável, para iniciar várias variáveis são necessárias outras tantas instruções. A sequência de valores iniciais não pode conter identificadores que denotem constantes, variáveis ou funções, nem tão pouco expressões, mesmo que estas só contenham valores constantes e literais. Exemplos: init meses := [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ] init dias := [ 365 ] init nome := Gollum Note-se que uma variável denota sempre uma posição de memória, logo dias + 1 = 366 é uma condição verdadeira e equivalente a dias[0] + 1 = 366, so possível indexar qualquer variável. A inicialização de uma cadeia de caracteres corresponde à definição de uma variável cujo valor é o ereço inicial da cadeia. O conteúdo da cadeia é constante. 4.2.2 Variáveis não iniciadas A definição de variáveis escalares não iniciadas começa com a palavras chave var seguida de de um tipo (opcional, por omissão inteiro) e uma sequência de identificadores separados por vírgulas. Exemplos: var dias, horas var integer minutos, segundos var real comprimento, altura A dimensão das variáveis não iniciadas não escalares (vectores) é indicada entre parentesis rectos. Se a dimensão for omitida, a reserva de memória deve ser efectuada pela operação de reserva de memória ( 7.8). Exemplos: 6

var pilha[20], aux[] var real coordenadas[3] 5 Declarações exteriores A declaração de entidades exteriores só pode ser efectuada fora das funções. A definição de entidades exteriores começa com a palavra chave extern seguida de uma sequência não nula de identificadores.esta declaração permite a utilização de compilação separada. 6 Funções Uma função permite agrupar um conjunto de instruções num corpo, que é executado com base num conjunto de parâmetros (os argumentos formais) quando é invocada a partir de uma expressão. O programa tem início na função com nome start. 6.1 Declaração As funções que recebam argumentos devem indicá-los no cabeçalho. Funções sem argumentos definem um cabeçalho vazio. Uma declaração de uma função sem corpo é utilizada para tipificar um identificador exterior ou para efectuar declarações antecipadas (utilizadas para pré-declarar funções que sejam usadas antes de ser definidas, por exemplo, entre duas funções mutuamente recursivas). Caso a declaração tenha corpo, define-se uma nova função. A existência de corpo apenas pode uma única vez para um dado nome. Múltiplas declarações sem corpo com o mesmo nome são possíveis, mas têm de concordar nos tipos do retorno e dos argumentos. Todas as funções devem indicar o tipo de retorno (por omissão, o tipo é inteiro). Quando invocadas devolvem sempre um valor do tipo indicado. 6.2 Invocação A função só pode ser invocada através de um identificador que refira uma função previamente declarada ou definida. Caso existam argumentos, na invocação da função, o seu identificador é seguido de uma lista de expressões delimitadas por parênteses curvos. A lista de expressões é uma sequência, possivelmente vazia, de expressões separadas por vírgulas. As expressões são avaliadas da direita para a esquerda antes da invocação da função (convenção Cdecl) e o valor resultante passado por cópia (passagem de argumentos por valor). O número e tipo de parâmetros actuais deve ser igual ao número e tipo dos parâmetros formais da função invocada (i.e., não existem parâmetros opcionais). A ordem dos parâmetros actuais deverá ser a mesma dos argumentos formais da função invocada. Os parâmetros actuais devem ser colocados na pilha de dados pela ordem inversa da sua declaração (o primeiro no topo da pilha) e o ereço de retorno no topo da pilha. A função chamadora coloca os argumentos na pilha e é também responsável pela sua remoção, após o retorno da função chamada (convenção Cdecl). Ainda de acordo com esta convenção, a passagem de retorno que não é possível colocar num registo é feita por referência passada como o primeiro argumento (i.e., o chamador reserva o espaço necessário e envia a localização à função invocada). 6.3 Corpo O valor devolvido por uma função, definido através do left-value especial que tem o mesmo nome da função, deve ser sempre do tipo declarado. Podem ser realizadas várias atribuições durante a vida da função, so retornado o valor existente quando a função termina. O nome da variável de retorno é reservado na função correspondente, não podo ser reutilizado como variável local ou nome de um argumento. Os nomes das variáveis (ao corpo da função) não podem ser iguais aos dos argumentos da função. Uma instrução return causa a interrupção imediata da função. 7

6.4 Função principal e execução de programas A execução de um programa inicia-se com a invocação da função designada por start e que não recebe argumentos. Os argumentos com que o programa foi chamado podem ser obtidos através de funções: argc() devolve o número de argumentos; string argv(integer n) devolve o n-ésimo argumento como um ponteiro para uma cadeia de caracteres (n > 0); e string envp(integer n) devolve a n-ésima variável de ambiente como um ponteiro para uma cadeia de caracteres (n > 0). O valor de retorno desta função é devolvido ao ambiente que invocou o programa. Este valor de retorno segue as seguintes regras (sistema operativo): 0 (zero) se a execução correu sem erros, 1 (um) se os argumentos são em número ou valor inválido, 2 (dois) erro detectado durante a execução. Os valores superiores a 128 indicam que o programa terminou com um sinal. Em geral, para correcto funcionamento, exige-se que os programas devolvam 0 (zero) se a execução foi bem sucedida e um valor diferente de 0 (zero) se ocorreu um erro. A biblioteca de run-time (RTS) contém mais informação sobre as rotinas de baixo nível disponíveis para o desenvolvimento do compilador. 7 Instruções Excepto quando indicado, as instruções são executadas em sequência, so os seus efeitos traduzidos, em geral, pela alteração do valor de variáveis. As instruções são separadas pelas mudanças de uma linha lógica para a seguinte. 7.1 Expressão como instrução Quando uma expressão figurar numa linha lógica, é utilizada como instrução, mesmo que não produza qualquer efeito secundário. A avaliação da expressão é realizada como habitualmente, mas o seu valor é descartado. 7.2 Blocos Um bloco é definido pelas mudanças de indentação que ocorrem nos seus limites: um aumento marca o seu início e uma diminuição o seu fim. Durante o bloco, a indentação é constante. Cada bloco tem uma zona de declarações locais (facultativa): constantes e variáveis. A zona de declarações é seguida por uma zona (não nula) com instruções. O tempo de vida das variáveis, bem como a sua visibilidade, é limitada ao fim do bloco em que foram declaradas. As entidades declaradas podem ser directamente utilizadas em sub-blocos ou passadas como argumentos para funções dentro do bloco. Caso os identificadores usados para definir as constantes e variáveis locais já estejam a ser utilizados para definir outras entidades ao alcance do bloco, o novo identificador passa a referir uma nova entidade definida no bloco até ao que ele termine (a entidade previamente definida continua a existir, mas não pode ser directamente referida pelo seu nome). Esta regra não se aplica à redefinição de variáveis com o mesmo nome da função actual ou dos seus argumentos (ambas são proibidas) (ver 6.3). 7.3 Instrução condicional Se a expressão que segue a palavra chave if for diferente de 0 (zero) então a instrução que segue a palavra then é executado. Caso contrário, se existir uma palavra, a instrução correspondente é executada. 7.4 Instruções de iteração O ciclo do-until- é semelhante ao ciclo do-while da linguagem C. A parte alternativa () é executada se a condição em until nunca for verdadeira (i.e., não é executada quando o ciclo, depois de executar com condições verdadeiras, termina). O ciclo while-do- é semelhante ao ciclo while da linguagem C. A parte alternativa () é executada se a condição em while nunca for verdadeira (i.e., não é executada quando o ciclo, depois de executar, termina). 7.5 Instrução de retorno Indicada pela palavra reservada return, a existir deverá ser a última instrução do bloco em que se insere. Ver 6.3. 8

7.6 Instrução de continuação Iniciada pela palavra reservada continue, a existir deverá ser a última instrução do bloco em que se insere. Esta instrução reinicia o ciclo mais interior em que a instrução se encontrar, tal como a instrução continue em C. Quando seguida de um número inteiro n, reinicia o n-ésimo ciclo a contar do actual (n = 1). Esta instrução só pode existir dentro de um ciclo. A especificação de um número maior que aninhamento dos ciclos é um erro. 7.7 Instrução de terminação Iniciada pela palavra reservada break, a existir deverá ser a última instrução do bloco em que se insere. Esta instrução termina a execução do ciclo interior em que a instrução se encontrar, tal como a instrução break em C. Quando seguida de um número inteiro n, termina o n-ésimo ciclo a contar do actual (n = 1). Esta instrução só pode existir dentro de um ciclo e obriga à reavaliação da condição de iteração do ciclo. A especificação de um número maior que aninhamento dos ciclos é um erro. 7.8 Reserva de memória A expressão reserva de memória devolve o ponteiro que aponta para a zona de memória na pilha da função actual conto espaço suficiente para o número de bytes indicados pelo seu argumento inteiro. O tipo de retorno é idêntico ao do left-value utilizado. O identificador da zona de memória deve ser declarado como um vector sem dimensão, podo ser um argumento de função. 8 Expressões Uma expressão é uma representação algébrica de uma quantidade. Assim, todas as expressões devolvem um valor. As expressões utilizam operadores algébricos comuns (e.g., soma, subtracção), operadores lógicos (e.g., negação) e relacionais (e.g., maior ou igual). Se a um operador forem passados valores inteiros e reais, os inteiros devem ser promovidos ao valor real correspondente. Analogamente, um inteiro pode ser utilizado onde é esperado um real, devo ser promovido antes da sua utilização. As expressões são sempre avaliadas da esquerda para a direita, indepentemente da associatividade do operador. A precedência dos operadores é a mesma para operadores na mesma secção, so as secções seguintes de menor prioridade que as anteriores. O valor resultante da aplicação da expressão bem como a sua associatividade são indicados para cada operador. A tabela seguinte que resume os operadores, por grupos de precedência decrescente: parênteses ( ) não associativo indexação [ ] da esquerda para a direita posição @ (prefixo) não associativo leitura? (sufixo) não associativo incremento/decremento -- ++ (prefixo ou sufixo) não associativos unária - + (prefixo) não associativos não lógico not (prefixo) não associativo potência ** da direita para a esquerda multiplicativa * / % da esquerda para a direita aditiva + - da esquerda para a direita compação < > <= >= não associativos igualdade = <> da esquerda para a direita e lógico and da esquerda para a direita ou lógico or da esquerda para a direita atribuição := da direita para a esquerda escrita!!! (sufixo) não associativo Operadores com o mesmo nome que em C têm, em geral, o mesmo significado que em C (excepto como indicado nesta secção). 8.1 Expressões primárias 8.1.1 Identificadores Um identificador é uma expressão desde que tenha sido devidamente declarado. Um identificador corresponde a um nome de variável, constante, ou de função. 9

Um identificador é o caso mais simples de um left-value, i.e., uma entidade que pode ser utilizada no lado esquerdo (left-value) de uma atribuição. O nome de uma função constitui um identificador especial dentro da função actual, designando o valor de retorno. 8.1.2 Literais Os literais podem ser valores constantes inteiros não negativos, reais, ou cadeias de caracteres, tal como definidos nas convenções lexicais. Ver 2.5. 8.1.3 Parênteses curvos Uma expressão entre parênteses curvos tem o valor da expressão sem os parênteses e permite alterar a prioridade dos operadores. Uma expressão entre parênteses não pode ser utilizada como left-value (ver 8.1.4). 8.1.4 Indexação Uma expressão indexação devolve o valor da posição indicada por um ponteiro. É uma expressão ponteiro seguida do índice entre parênteses rectos. O resultado de uma expressão de indexação é o valor existente na posição de memória base somado com o deslocamento, em quantidades da dimensão do tipo do valor da expressão. O primeiro elemento tem deslocamento 0 (zero). Se a expressão ponteiro for um left-value, então a expressão indexação poderá também ser um left-value. Exemplo: p[0] (acesso à posição apontada por p). 8.1.5 Invocação de funções Ver 6.2. 8.2 Expressões unárias 8.2.1 Expressão de indicação de posição A expressão localização (@) devolve a posição de memória ocupada pelo left-value indicado como argumento. Retorna um valor do tipo do ponteiro apropriado para o objecto em causa. Exemplo: @p indica a posição de memória de p. 8.2.2 Leitura A operação de leitura (?) permite atribuir ao left-value indicado um valor inteiro ou real. A operação retorna o valor inteiro 1 (um), se tiver conseguido ler o valor, -1 (menos um) se se chegar ao fim do canal (EOF), e 0 (zero) nos restantes casos. 8.2.3 Identidade A expressão identidade (+) devolve o valor do seu argumento inteiro ou real. 8.2.4 Simétrico A expressão valor simétrico (-) devolve o simétrico do seu argumento inteiro ou real. 8.2.5 Incremento O operador de incremento (++) incrementa em uma unidade o valor do left-value passado como argumento. A operação é um pré-incremento (utilização prefixa), ou um pós-incremento (utilização sufixa). Notar que x := x + 1 ou x[0]++ correspondem a incrementos de uma unidade o primeiro valor de x, enquanto x++ corresponde a um avanço do ponteiro para o valor seguinte (apenas possível quando x corresponder a um ponteiro declarado var x[] ou equivalente). 10

8.2.6 Decremento O operador de decremento (--) decrementa em uma unidade o valor do left-value passado como argumento. A operação é um pré-decremento (utilização prefixa), ou um pós-decremento (utilização sufixa). As disposições enunciadas para o incremento são aplicáveis ao decremento. 8.3 Expressão de potência A operação de potência (**) é apenas aplicável a valores inteiros, devolvo a multiplicação do primeiro argumento por ele próprio tantas vezes quantas o valor do segundo argumento. 8.4 Expressões multiplicativas As operações são apenas aplicáveis a valores inteiros e reais (excepto nas condições especiais assinaladas), devolvo o resultado da respectiva operação algébrica. A divisão (/) é inteira se ambos os operandos o forem. É um erro o denominador ter o valor 0 (zero), tanto no caso da divisão, como no caso do resto da divisão. 8.4.1 Multiplicação A multiplicação (*) corresponde à operação algébrica se ambos os operandos forem inteiros ou reais (havo promoção de tipos quando necessário). É possível um uso especial da multiplicação em que o primeiro operando é uma cadeia de caracteres e o segundo um inteiro não negativo (outras combinações de ordem ou sinal são ilegais). Neste caso, a cadeia de caracteres é repetida tantas vezes quantas o valor do inteiro. Um valor 0 (zero) corresponde à cadeia nula. Exemplo: * (i * 2)! imprime uma sequência de caracteres brancos (de comprimento igual ao dobro do valor de i). 8.4.2 Resto de divisão inteira A operação de resto (%) é aplicável tanto a valores inteiros como a reais (os operandos reais são truncados). 8.5 Expressões aditivas As operações são apenas aplicáveis a valores inteiros e reais, devolvo o resultado da respectiva operação algébrica. Estas operações podem realizar-se sobre ponteiros, to o significado das operações correspondentes em C/C++: (i) deslocamentos, i.e., um dos operandos deve ser do tipo ponteiro e o outro do tipo inteiro; (ii) diferenças de ponteiros, i.e., apenas quando se aplica o operador - a dois ponteiros do mesmo tipo (o resultado é o número de objectos do tipo apontado entre eles). 8.5.1 Somas e cadeias de caracteres Quando um dos elementos da soma é uma cadeia de carateres, quer sob a forma de um literal quer sob a forma de uma constante, o resultado é também uma cadeia de caracteres. Assim, a soma de duas cadeias de caracteres resulta numa cadeia de caracteres que é a concatenação de ambas as sequências. Por outro lado, se um dos elementos for um inteiro ou um real e o outro uma cadeia de caracteres, o inteiro é convertido numa cadeia de caracteres, e o resultado é a concatenação do valor convertido com a cadeia de caracteres. A ordem pela qual as cadeias surjem na cadeia final depe da ordem em que surgem na operação de soma. 8.6 Expressões de comparação As operações (< <= >= >) são aplicáveis a valores inteiros ou reais. Devolvem o valor inteiro 0 (zero) caso a comparação seja falsa e o valor inteiro 1 (um) em caso contrário. 11

8.7 Expressões de igualdade As operações igual (=) e diferente (<>) são aplicáveis a valores inteiros e reais. Devolvem o valor inteiro 0 (zero) caso a comparação seja falsa e o valor inteiro 1 (um) em caso contrário. 8.8 Expressões de negação lógica A operação (not) é aplicável a valores inteiros e retorna valores inteiros. O valor 0 (zero) representa a condição falsa e o valor 1 (um) a condição verdadeira. 8.9 Expressão de junção lógica A operação (and) é aplicável a valores inteiros, devolvo um valor diferente de zero caso ambos os argumentos sejam diferente de 0 (zero) e um valor diferente de zero caso contrário. Caso o primeiro argumento seja 0 (zero) o segundo argumento não deve ser avaliado. 8.10 Expressão de alternativa lógica A operação (or) é aplicável a valores inteiros, devolvo o valor inteiro 0 (zero) caso ambos os argumentos sejam iguais a 0 (zero) e um valor diferente de zero caso contrário. Caso o primeiro argumento seja um valor diferente de zero o segundo argumento não deve ser avaliado. 8.11 Expressão de atribuição O valor da expressão do lado direito do operador (:=) é guardado na posição indicada pelo left-value do lado esquerdo do operador de atribuição. O uso de um real na atribuição a um inteiro é possível e implica uma operação de truncatura. Notar, no exemplo seguinte, que o valor j+5 é colocado em base[j+5], por causa da associatividade do operador. a := base[i] := i := j + 5 8.12 Expressão de escrita A operação de escrita (! ou!!) permite apresentar num canal de saída o valor do seu operando. A versão!! adiciona um caracter de mudança de linha ao valor da expressão. O valor devem ser apresentados em decimal para os valores numéricos e em ASCII e ISO 8859-15 para valores do tipo string. 9 Exemplos Os exemplos apresentados não são exaustivos, pelo que não ilustram todos os aspectos da linguagem. 9.1 Cálculo do factorial Dois programas para cálculo do factorial. 12

# Factorial recursivo (com função) factorial(n) if n > 1 then factorial := n * factorial(n-1) factorial := n init f = [ 5 ] start() if argc() = 1 then f = atoi(argv(1)) f +! = + factorial(f)!! start := 0 # Factorial iterativo (sem função) start() var f, n, i if argc() = 1 then n := atoi(argv(1)) n := 5 f := i := n while i > 2 do i := i - 1 f := f * i done n +! = + f!! start := 0 9.2 Cálculo de termos da série de Fibonacci Cálculo recursivo de um termo da série de Fibonacci: fibonacci(n) if n = 0 or n = 1 then fibonacci := n fibonacci := fibonacci(n-1) + fibonacci(n-2) start() var n Introduza um número inteiro positivo:! if n? <> 1 or n <= 0 then start := 1 Fibonacci( +n+ ) = +fibonacci(n)!! start := 0 10 Omissões Casos omissos e erros serão corrigidos em futuras versões do manual de referência. 13