pl0編譯程序的源程序在哪
改名:mv hello hello.c
編譯:首先cd到你源文件的那個目錄下,這樣省去了指定絕對路徑的麻煩,比如cd到桌面,然後:gcc hello.c -o hello
運行:./hello
② 什麼是文件的源程序怎樣打開文件的源程序
1.理論上的概念
源代碼是相對目標代碼和可執行代碼而言的。
源代碼就是用匯編語言和高級語言寫出來的地代碼。
目標代碼是指源代碼經過編譯程序產生的能被cpu直接識別二進制代碼。
可執行代碼就是將目標代碼連接後形成的可執行文件,當然也是二進制的。
2.最直觀的概念
在這個網頁上右鍵滑鼠,選擇查看源文件.出來一個記事本,裡面的內容就是此網頁的源代碼.
===================================================
關於兩者的區別聯系:
1.從字面意義上來講,源文件是指一個文件,指源代碼的集合.源代碼則是一組具有特定意義的可以實現特定功能的字元(程序開發代碼).
2."源代碼"在大多數時候等於"源文件".
楓舞在上面說過"2.最直觀的概念 在這個網頁上右鍵滑鼠,選擇查看源文件.出來一個記事本,裡面的內容就是此網頁的源代碼."這句話就體現了他們的關系,此處的源文件是指網頁的源文件,而源代碼就是源文件的內容,所以又可以稱做網頁的源代碼..
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
楓舞添言:
1.楓舞有個好朋友認為「源代碼」就是「原始人寫出的代碼」,楓舞一直也沒有時間考察他的正確性 ^-^
2.楓舞忽然想起小時候造句,突發奇想給你造個句子肯定可以幫助理解..
關鍵詞:源文件
造句:小趙,幫我把源文件拷貝到我的硬碟.復制兩份.文件名定為file1.asp file2.asp
關鍵詞:源代碼
造句:小李,把源代碼中的第8行刪除.哦~源代碼(源文件亦可)小趙發到我硬碟了,待會給你傳過去.就是file1.asp.
③ 軟體的源程序裝在哪裡
不管是什麼語言寫的,最終都會編譯成二進制文件,在編譯後的程序是找不到源代碼的。除非是反編譯程序來實現,當然像.net的程序是可以基本反編譯的,反出來的代碼和原來編譯前的基本一致,像VB,VC等編程語言是沒有反編譯程序的,除了拿到作者的源代碼,否則看不到源代碼。
不過,有反匯編的方式,這個方式看到的是匯編代碼,分析這些可以分析程序的行為等,這就不詳細說了。
good luck
④ pl0怎麼擴展++,--功能
那我給你網站吧,我找很久了.那個東西是很需要的
http://download.csdn.net/source/191218
PL/0語言是Pascal語言的一個子集,這里分析的PL/0的編譯程序包括了對PL/0語
言源程序進行分析處理、編譯生成類PCODE代碼,並在虛擬機上解釋運行生成的類PCODE代碼的功能。
PL/0語言編譯程序採用以語法分析為核心、一遍掃描的編譯方法。詞法分析和代碼生成作為獨立的子程序供語法分析程序調用。語法分析的同時,提供了出錯報告和出錯恢復的功能。在源程序沒有錯誤編譯通過的情況下,調用類PCODE解釋程序解釋執行生成的類PCODE代碼。
2.各功能模塊描述
詞法分析子程序分析:
詞法分析子程序名為GETSYM,功能是從源程序中讀出一個單詞符號(TOTAKEN),把它的信息放入全局變數 SYM、ID和NUM中,字元變數放入CH中,語法分析器需要單詞時,直接從這三個變數中獲得。Getch過程通過反復調用Getch子過程從源程序過獲取字元,並把它們拼成單詞。GETCH過程中使用了行緩沖區技術以提高程序運行效率。
詞法分析器的分析過程:調用GETSYM時,它通過GETCH過程從源程序中獲得一個字元。如果這個字元是字母,則繼續獲取字元或數字,最終可以拼成一個單詞,查保留字表,如果查到為保留字,則把SYM變數賦成相應的保留字類型值;如果沒有查到,則這個單詞應是一個用戶自定義的標識符(可能是變數名、常量名或是過程的名字),把SYM置為IDENT,把這個單詞存入ID變數。查保留字表時使用了二分法查找以提高效率。如果Getch獲得的字元是數字,則繼續用Getch獲取數字,並把它們拼成一個整數或實數,然後把SYM置為 INTEGER或REAL,並把拼成的數值放入NUM變數。如果識別出其它合法的符號(比如:賦值號、大於號、小於等於號等),則把SYM則成相應的類型。如果遇到不合法的字元,把SYM置成NUL。
語法分析子程序分析:
語法分析子程序採用了自頂向下的遞歸子程序法,語法分析同時也根據程序的語義生成相應三元代碼,並提供了出錯處理的機制。語法分析主要由分程序分析過程(BLOCK)、參數變數分析過程(ParaDeclaration)、參數變數處理過程(ParaGetSub)、數組處理過程(ParaGetSub)、常量定義分析過程(ConstDeclaration)、變數定義分析過程(Vardeclaration)、語句分析過程(Statement)、表達式處理過程(Expression)、項處理過程(Term)、因子處理過程(Factor)和條件處理過程(Condition)構成。這些過程在結構上構成一個嵌套的層次結構。除此之外,還有出錯報告過程(Error)、代碼生成過程(Gen)、測試單詞合法性及出錯恢復過程(Test)、登錄名字表過程(Enter)、查詢名字表函數(Position)以及列出類 PCODE代碼過程(Listcode)作過語法分析的輔助過程。
由PL/0的語法圖可知:一個完整的PL/0程序是由分程序和句號構成的。因此,本編譯程序在運行的時候,通過主程序中調用分程序處理過程block來分析分程序部分(分程序分析過程中還可能會遞歸調用block過程),然後,判斷最後讀入的符號是否為句號。如果是句號且分程序分析中未出錯,則是一個合法的PL/0程序,可以運行生成的代碼,否則就說明源PL/0程序是不合法的,輸出出錯提示即可。
下面按各語法單元分析PL/0編譯程序的運行機制。
分程序處理過程:
語法分析開始後,首先調用分程序處理過程(Block)處理分程序。過程入口參數置為:0層、符號表位置0、出錯恢復單詞集合為句號、聲明符或語句開始符。進入Block過程後,首先把局部數據段分配指針設為3,准備分配3個單元供運行期存放靜態鏈SL、動態鏈DL 和返回地址RA。然後用Tx0記錄下當前符號表位置並產生一條Jmp指令,准備跳轉到主程序的開始位置,由於當前還沒有知到主程序究竟在何處開始,所以 Jmp的目標暫時填為0,稍後再改。同時在符號表的當前位置記錄下這個Jmp指令在代碼段中的位置。在判斷了嵌套層數沒有超過規定的層數後,開始分析源程序。首先判斷是否遇到了常量聲明,如果遇到則開始常量定義,把常量存入符號表。接下去用同樣的方法分析變數聲明,變數定義過程中會用Dx變數記錄下局部數據段分配的空間個數。然後如果遇到Procere保留字則進行過程聲明和定義,聲明的方法是把過程的名字和所在的層次記入符號表,過程定義的方法就是通過遞歸調用Block過程,因為每個過程都是一個分程序。由於這是分程序中的分程序,因此調用Block時需把當前的層次號Lev加一傳遞給Block 過程。分程序聲明部分完成後,即將進入語句的處理,這時的代碼分配指針CX的值正好指向語句的開始位置,這個位置正是前面的Jmp指令需要跳轉到的位置。於是通過前面記錄下來的地址值,把這個Jmp指令的跳轉位置改成當前cx的位置。並在符號表中記錄下當前的代碼段分配地址和局部數據段要分配的大小(DX 的值)。生成一條INT指令,分配DX個空間,作為這個分程序段的第一條指令。下面就調用語句處理過程Statement分析語句。分析完成後,生成操作數為0的OPR指令,用於從分程序返回(對於0層的主程序來說,就是程序運行完成,退出)。
常量定義過程:
通過循環,反復獲得標識符和對應的值,存入符號表。符號表中記錄下標識符的名字和它對應的值。
變數定義過程:
與常量定義類似,通過循環,反復獲得標識符,存入符號表。符號表中記錄下標識符的名字、它所在的層及它在所在層中的偏移地址。
參變數定義過程:
類似變數定義,將參變數,存入符號表中。
參變數處理過程:
如果函數用參變數,依照形參的類型、個數,由實參進行賦值。
數組處理過程:
計算數組括弧內的偏移值,存入棧頂用於後面生成的STOARR和LODARR指令調用實際的數組中元素的地址。
語句處理過程:
語句處理過程是一個嵌套子程序,通過調用表達式處理、項處理、因子處理等過程及遞歸調用自己來實現對語句的分析。語句處理過程可以識別的語句包括賦值語句、read語句、write語句、++語句、--語句、+=語句、-=語句、if-else-then語句、while語句、For語句、repeat 語句。當遇到begin/end語句時,就遞歸調用自己來分析。分析的同時生成相應的類PCODE指令。
賦值語句的處理:
首先獲取賦值號左邊的標識符,從符號表中找到它的信息,並確認這個標識符確為變數名。然後通過調用表達式處理過程算得賦值號右部的表達式的值並生成相應的指令保證這個值放在運行期的數據棧頂。最後通過前面查到的左部變數的位置信息,生成相應的STO指令,把棧頂值存入指定的變數的空間,實現了賦值操作。返回函數值也是用賦值語句進行返回值的儲存。
對函數與過程調用的處理:
首先判斷讀入的標識符屬性為FUNCTION或PROCEDURE,從符號表中找到此標識符,獲得其所在層次和偏移地址。然後生成相應的cal指令。至於調用子過程所需的保護現場等工作是由類PCODE解釋程序在解釋執行cal指令時自動完成的。如果此標識符不在第0層而且是該層函數的函數名則作為返回值返回。
read語句的處理:
確定read語句語法合理的前提下(否則報錯),由變數的類型生成相應的指令:
對於整型,第一條是16號操作的opr指令,實現從標准輸入設備上讀一個整數值,放在數據棧頂。如果讀入是實數就報錯,第二條是sto指令,把棧頂的值存入read語句括弧中的變數所在的單元。
對於實型,第一條是15號操作的opr指令,實現從標准輸入設備上讀一個實數值,放在數據棧頂。第二條是sto指令,把棧頂的值存入read語句括弧中的變數所在的單元。
對於字元型,第一條是20號操作的opr指令,實現從標准輸入設備上讀一個字元值,第二條是sto指令,把棧頂的值存入read語句括弧中的變數所在的單元。
write語句的處理:
與read語句相似。在語法正確的前提下,生成指令:通過循環調用表達式處理過程分析write語句括弧中的每一個表達式,生成相應指令保證把表達式的值算出並放到數據棧頂並生成指令,輸出表達式的值,如果是數字類型則生成14號操作的opr指令,如果是字元類型則生成19號操作的opr指令。
if-then-else語句的處理:
按if語句的語法,首先調用邏輯表達式處理過程處理if語句的條件,把相應的真假值放到數據棧頂。接下去記錄下代碼段分配位置(即下面生成的jpc指令的位置),然後生成條件轉移jpc指令(遇0或遇假轉移),轉移地址未知暫時填0。然後調用語句處理過程處理 then語句後面的語句或語句塊。then後的語句處理完後,如果遇到else,就調用語句處理過程處理else語句後面的語句或語句塊,這時當前代碼段分配指針的位置就應該是上面的jpc指令的轉移位置。通過前面記錄下的jpc指令的位置,把它的跳轉位置改成當前的代碼段指針位置,否則沒遇到else,那麼此時的當前代碼段分配指針的位置也是上面jpc指令的轉移位置,也是通過前面記錄下的jpc位置指令的位置,把它的跳轉到當前的代碼段指針位置。
begin/end語句的處理:
通過循環遍歷begin/end語句塊中的每一個語句,通過遞歸調用語句分析過程分析並生成相應代碼。
while語句的處理:
首先用cx1變數記下當前代碼段分配位置,作為循環的開始位置。然後處理while語句中的條件表達式生成相應代碼把結果放在數據棧頂,再用cx2變數記下當前位置,生成條件轉移指令,轉移位置未知,填0。通過遞歸調用語句分析過程分析do語句後的語句或語句塊並生成相應代碼。最後生成一條無條件跳轉指令 jmp,跳轉到cx1所指位置,並把cx2所指的條件跳轉指令的跳轉位置改成當前代碼段分配位置。
Repeat語句的處理:
首先用CX1變數記下當前代碼段分配位置,作為循環的開始位置。然後通過遞歸調用語句分析過程分析,直到遇到until保留字,如果未對應until則出錯。調用條件表達式處理過程生成相應代碼把結果放在數據棧頂,再生成條件轉移指令,轉移位置為上面記錄的CX1。
For語句的處理:
按For語句的語法,首先對For後面的一個標識符進行初值的賦值過程(類似賦值語句處理),生成相應的代碼。之後遇到TO或DOWNTO保留字,如果未對應則出錯。用CX1變數記下當前代碼段分配的位置,作為以後JMP循環的開始位置。對上面識別的標識符變數進行存取,與TO或DOWNTO後面的表達式進行比較,生成比較指令(TO為13、DOWNTO為11),再用CX2變數記下當前代碼段分配的位置,生成JPC指令,跳轉地址未知,之後可用CX2記錄下的位置進行回填。然後處理DO保留字後的循環體,第一步遞歸調用語句分析過程,第二步將原先For後的標識符變數進行自加處理,生成相應代碼,然後生成無條件跳轉語句JMP跳轉代碼為CX1。最後將此時的代碼段位置回填到JPC跳轉指令上。
表達式、項、因子處理:
根據PL/0語法可知,表達式應該是由正負號或無符號開頭、由若干個項以加減號連接而成。而項是由若干個因子以乘除號,mod、div符號或++、--符號連接而成,因子則可能是一個標識符或一個數字,或是一個以括弧括起來的子表達式。根據這樣的結構,構造出相應的過程,遞歸調用就完成了表達式的處理。把項和因子獨立開處理解決了加減號與乘除號的優先順序問題。在這幾個過程的反復調用中,始終傳遞fsys變數的值,保證可以在出錯的情況下跳過出錯的符號,使分析過程得以進行下去。
邏輯表達式的處理:
首先判斷是否為一元邏輯表達式:判奇偶。如果是,則通過調用表達式處理過程分析計算表達式的值,然後生成判奇指令。如果不是,則肯定是二元邏輯運算符,通過調用表達式處理過程依次分析運算符左右兩部分的值,放在棧頂的兩個空間中,然後依不同的邏輯運算符,生成相應的邏輯判斷指令,放入代碼段。
判斷單詞合法性與出錯恢復過程分析:
本過程有三個參數,s1、s2為兩個符號集合,n為出錯代碼。本過程的功能是:測試當前符號(即sym變數中的值)是否在s1集合中,如果不在,就通過調用出錯報告過程輸出出錯代碼n,並放棄當前符號,通過詞法分析過程獲取一下單詞,直到這個單詞出現在s1或s2集合中為止。
這個過程在實際使用中很靈活,主要有兩個用法:
在進入某個語法單位時,調用本過程,檢查當前符號是否屬於該語法單位的開始符號集合。若不屬於,則濾去開始符號和後繼符號集合外的所有符號。
在語法單位分析結束時,調用本過程,檢查當前符號是否屬於調用該語法單位時應有的後繼符號集合。若不屬於,則濾去後繼符號和開始符號集合外的所有符號。
通過這樣的機制,可以在源程序出現錯誤時,及時跳過出錯的部分,保證語法分析可以繼續下去。
語法分析過程中調用的其它子過程相對比較簡單,請參考源程序的注釋。
類PCODE代碼解釋執行過程分析:
這個過程模擬了一台可以運行類PCODE指令的棧式計算機。它擁有一個棧式數據段用於存放運行期數據、擁有一個代碼段用於存放類PCODE程序代碼。同時還擁用數據段分配指針、指令指針、指令寄存器、局部段基址指針等寄存器。
解釋執行類PCODE代碼時,數據段存儲分配方式如下:
對於源程序的每一個過程(包括主程序),在被調用時,首先在數據段中開辟三個空間,存放靜態鏈SL、動態鏈DL和返回地址RA。靜態鏈記錄了定義該過程的直接外過程(或主程序)運行時最新數據段的基地址。動態鏈記錄調用該過程前正在運行的過程的數據段基址。返回地址記錄了調用該過程時程序運行的斷點位置。對於主程序來說,SL、DL和RA的值均置為0。靜態鏈的功能是在一個子過程要引用它的直接或間接父過程(這里的父過程是按定義過程時的嵌套情況來定的,而不是按執行時的調用順序定的)的變數時,可以通過靜態鏈,跳過個數為層差的數據段,找到包含要引用的變數所在的數據段基址,然後通過偏移地址訪問它。
在過程返回時,解釋程序通過返回地址恢復指令指針的值到調用前的地址,通過當前段基址恢復數據段分配指針,通過動態鏈恢復局部段基址指針。實現子過程的返回。對於主程序來說,解釋程序會遇到返回地址為0的情況,這時就認為程序運行結束。
解釋程序過程中的base函數的功能,就是用於沿著靜態鏈,向前查找相差指定層數的局部數據段基址。這在使用sto、lod、stoArr、lodArr等訪問局部變數的指令中會經常用到。
類PCODE代碼解釋執行的部分通過循環和簡單的case判斷不同的指令,做出相應的動作。當遇到主程序中的返回指令時,指令指針會指到0位置,把這樣一個條件作為終至循環的條件,保證程序運行可以正常的結束
⑤ 求一個c語言編寫的pl0編譯器
// pl0 compiler source code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "set.h"
#include "pl0.h"
//////////////////////////////////////////////////////////////////////
// print error message.
void error(n)
{
int i;
printf(" ");
for (i = 1; i <= cc - 1; i++)
printf(" ");
fprintf(outfile, " ");
fprintf(outfile, "^\n");
printf("^\n");
fprintf(outfile, "Error %3d: %s\n", n, err_msg[n]);
printf("Error %3d: %s\n", n, err_msg[n]);
err++;
} // error
//////////////////////////////////////////////////////////////////////
void getch(void)
{
if (cc == ll)
{
if (feof(infile))
{
printf("\nPROGRAM INCOMPLETE\n");
exit(1);
}
ll = cc = 0;
fprintf(outfile, "%5d ", cx);
printf("%5d ", cx);
while ( (!feof(infile)) // added & modified by alex 01-02-09
&& ((ch = getc(infile)) != '\n'))
{
fprintf(outfile, "%c", ch);
printf("%c", ch);
line[++ll] = ch;
} // while
fprintf(outfile, "\n");
printf("\n");
line[++ll] = ' ';
}
ch = line[++cc];
} // getch
//////////////////////////////////////////////////////////////////////
// gets a symbol from input stream.
void getsym(void)
{
int i, k;
char a[MAXIDLEN + 1];
while (ch == ' '|| ch == '\t')
// modified by yzhang 02-03-12,add some white space
getch();
if (isalpha(ch))
{ // symbol is a reserved word or an identifier.
k = 0;
do
{
if (k < MAXIDLEN)
a[k++] = ch;
getch();
}
while (isalpha(ch) || isdigit(ch));
a[k] = 0;
strcpy(id, a);
word[0] = id;
i = NRW;
while (strcmp(id, word[i--]));
if (++i)
sym = wsym[i]; // symbol is a reserved word
else
sym = SYM_IDENTIFIER; // symbol is an identifier
}
else if (isdigit(ch))
{ // symbol is a number.
k = num = 0;
sym = SYM_NUMBER;
do
{
num = num * 10 + ch - '0';
k++;
getch();
}
while (isdigit(ch));
if (k > MAXNUMLEN)
error(25); // The number is too great.
}
else if (ch == ':')
{
getch();
if (ch == '=')
{
sym = SYM_BECOMES; // :=
getch();
}
else
{
sym = SYM_NULL; // illegal?
}
}
else if (ch == '>')
{
getch();
if (ch == '=')
{
sym = SYM_GEQ; // >=
getch();
}
else
{
sym = SYM_GTR; // >
}
}
else if (ch == '<')
{
getch();
if (ch == '=')
{
sym = SYM_LEQ; // <=
getch();
}
else if (ch == '>')
{
sym = SYM_NEQ; // <>
getch();
}
else
{
sym = SYM_LES; // <
}
}
else
{ // other tokens
i = NSYM;
csym[0] = ch;
while (csym[i--] != ch);
if (++i)
{
sym = ssym[i];
getch();
}
else
{
printf("Fatal Error: Unknown character.\n");
fprintf(outfile, "Fatal Error: Unknown character.\n");
exit(1);
}
}
} // getsym
//////////////////////////////////////////////////////////////////////
// generates (assembles) an instruction.
void gen(int x, int y, int z)
{
if (cx > CXMAX)
{
fprintf(outfile, "Fatal Error: Program too long.\n");
printf("Fatal Error: Program too long.\n");
exit(1);
}
code[cx].f = x;
code[cx].l = y;
code[cx++].a = z;
} // gen
//////////////////////////////////////////////////////////////////////
// tests if error occurs and skips all symbols that do not belongs to s1 or s2.
void test(symset s1, symset s2, int n)
{
symset s;
if (! inset(sym, s1))
{
showset(s1);
showset(s2);
printf("sym=%d, id=%s\n", sym, id);
error(n);
s = uniteset(s1, s2);
while(! inset(sym, s))
getsym();
destroyset(s);
}
} // test
//////////////////////////////////////////////////////////////////////
int dx; // data allocation index
// enter object(constant, variable or procedre) into table.
void enter(int kind)
{
mask* mk;
// added by yzhang 02-02-28
if ( position(id)> 0 ){
error(26); //Redeclared identifier.
}
// end
tx++;
strcpy(table[tx].name, id);
table[tx].kind = kind;
switch (kind)
{
case ID_CONSTANT:
if (num > MAXADDRESS)
{
error(25); // The number is too great.
num = 0;
}
table[tx].value = num;
break;
case ID_VARIABLE:
mk = (mask*) &table[tx];
mk->level = level;
mk->address = dx++;
break;
case ID_PROCEDURE:
mk = (mask*) &table[tx];
mk->level = level;
break;
} // switch
} // enter
//////////////////////////////////////////////////////////////////////
// locates identifier in symbol table.
int position(char* id)
{
int i;
strcpy(table[0].name, id);
i = tx + 1;
while (strcmp(table[--i].name, id) != 0);
return i;
} // position
//////////////////////////////////////////////////////////////////////
void constdeclaration()
{
if (sym == SYM_IDENTIFIER)
{
getsym();
if (sym == SYM_EQU || sym == SYM_BECOMES)
{
if (sym == SYM_BECOMES)
error(1); // Found ':=' when expecting '='.
getsym();
if (sym == SYM_NUMBER)
{
enter(ID_CONSTANT);
getsym();
}
else
{
error(2); // There must be a number to follow '='.
}
}
else
{
error(3); // There must be an '=' to follow the identifier.
}
}
else //added by yzhang 02-02-28
error(4); // There must be an identifier to follow 'const', 'var', or 'procere'.
} // constdeclaration
//////////////////////////////////////////////////////////////////////
void vardeclaration(void)
{
if (sym == SYM_IDENTIFIER)
{
enter(ID_VARIABLE);
getsym();
}
else
{
error(4); // There must be an identifier to follow 'const', 'var', or 'procere'.
}
} // vardeclaration
//////////////////////////////////////////////////////////////////////
void listcode(int from, int to)
{
int i;
printf("\n");
fprintf(outfile, "\n");
for (i = from; i < to; i++)
{
printf("%5d %s\t%d\t%d\n", i, mnemonic[code[i].f], code[i].l, code[i].a);
fprintf(outfile, "%5d %s\t%d\t%d\n", i, mnemonic[code[i].f], code[i].l, code[i].a);
}
printf("\n");
fprintf(outfile, "\n");
} // listcode
//////////////////////////////////////////////////////////////////////
void factor(symset fsys)
{
void expression();
int i;
symset set;
test(facbegsys, fsys, 24); // The symbol can not be as the beginning of an expression.
while (inset(sym, facbegsys))
{
if (sym == SYM_IDENTIFIER)
{
if ((i = position(id)) == 0)
{
error(11); // Undeclared identifier.
}
else
{
switch (table[i].kind)
{
mask* mk;
case ID_CONSTANT:
gen(LIT, 0, table[i].value);
break;
case ID_VARIABLE:
mk = (mask*) &table[i];
gen(LOD, level - mk->level, mk->address);
break;
case ID_PROCEDURE:
error(21); // Procere identifier can not be in an expression.
break;
} // switch
}
getsym();
}
else if (sym == SYM_NUMBER)
{
if (num > MAXADDRESS)
{
error(25); // The number is too great.
num = 0;
}
gen(LIT, 0, num);
getsym();
}
else if (sym == SYM_LPAREN)
{
getsym();
set = uniteset(createset(SYM_RPAREN, SYM_NULL), fsys);
expression(set);
destroyset(set);
if (sym == SYM_RPAREN)
{
getsym();
}
else
{
error(22); // Missing ')'.
}
}
else // added by yzhang 02-02-28
test(fsys, createset(SYM_LPAREN, SYM_NULL), 23);
} // while
} // factor
//////////////////////////////////////////////////////////////////////
void term(symset fsys)
{
int mulop;
symset set;
set = uniteset(fsys, createset(SYM_TIMES, SYM_SLASH, SYM_NULL));
factor(set);
while (sym == SYM_TIMES || sym == SYM_SLASH)
{
mulop = sym;
getsym();
factor(set);
if (mulop == SYM_TIMES)
{
gen(OPR, 0, OPR_MUL);
}
else
{
gen(OPR, 0, OPR_DIV);
}
} // while
destroyset(set);
} // term
//////////////////////////////////////////////////////////////////////
void expression(symset fsys)
{
int addop;
symset set;
set = uniteset(fsys, createset(SYM_PLUS, SYM_MINUS, SYM_NULL));
if (sym == SYM_PLUS || sym == SYM_MINUS)
{
addop = sym;
getsym();
term(set);
if (addop == SYM_MINUS)
{
gen(OPR, 0, OPR_NEG);
}
}
else
{
term(set);
}
while (sym == SYM_PLUS || sym == SYM_MINUS)
{
addop = sym;
getsym();
term(set);
if (addop == SYM_PLUS)
{
gen(OPR, 0, OPR_ADD);
}
else
{
gen(OPR, 0, OPR_MIN);
}
} // while
destroyset(set);
} // expression
//////////////////////////////////////////////////////////////////////
void condition(symset fsys)
{
int relop;
symset set;
if (sym == SYM_ODD)
{
getsym();
expression(fsys);
gen(OPR, 0, 6);
}
else
{
set = uniteset(relset, fsys);
expression(set);
destroyset(set);
if (! inset(sym, relset))
{
error(20);
}
else
{
relop = sym;
getsym();
expression(fsys);
switch (relop)
{
case SYM_EQU:
gen(OPR, 0, OPR_EQU);
break;
case SYM_NEQ:
gen(OPR, 0, OPR_NEQ);
break;
case SYM_LES:
gen(OPR, 0, OPR_LES);
break;
case SYM_GEQ:
gen(OPR, 0, OPR_GEQ);
break;
case SYM_GTR:
gen(OPR, 0, OPR_GTR);
break;
case SYM_LEQ:
gen(OPR, 0, OPR_LEQ);
break;
} // switch
} // else
} // else
} // condition
//////////////////////////////////////////////////////////////////////
void statement(symset fsys)
{
int i, cx1, cx2;
symset set1, set;
if (sym == SYM_IDENTIFIER)
{ // variable assignment
mask* mk;
if (! (i = position(id)))
{
error(11); // Undeclared identifier.
}
else if (table[i].kind != ID_VARIABLE)
{
error(12); // Illegal assignment.
i = 0;
}
getsym();
if (sym == SYM_BECOMES)
{
getsym();
}
else
{
error(13); // ':=' expected.
}
expression(fsys);
mk = (mask*) &table[i];
if (i)
{
gen(STO, level - mk->level, mk->address);
}
}
else if (sym == SYM_CALL)
{ // procere call
getsym();
if (sym != SYM_IDENTIFIER)
{
error(14); // There must be an identifier to follow the 'call'.
}
else
{
if (! (i = position(id)))
{
error(11); // Undeclared identifier.
}
else if (table[i].kind == ID_PROCEDURE)
{
mask* mk;
mk = (mask*) &table[i];
gen(CAL, level - mk->level, mk->address);
}
else
{
error(15); // A constant or variable can not be called.
}
getsym();
} // else
}
else if (sym == SYM_IF)
{ // if statement
getsym();
set1 = createset(SYM_THEN, SYM_DO, SYM_NULL);
set = uniteset(set1, fsys);
condition(set);
destroyset(set1);
destroyset(set);
if (sym == SYM_THEN)
{
getsym();
}
else
{
error(16); // 'then' expected.
}
cx1 = cx;
gen(JPC, 0, 0);
statement(fsys);
code[cx1].a = cx;
}
else if (sym == SYM_BEGIN)
{ // block
getsym();
set1 = createset(SYM_SEMICOLON, SYM_END, SYM_NULL);
set = uniteset(set1, fsys);
statement(set);
while (sym == SYM_SEMICOLON || inset(sym, statbegsys))
{
if (sym == SYM_SEMICOLON)
{
getsym();
}
else
{
error(10);
}
statement(set);
} // while
destroyset(set1);
destroyset(set);
if (sym == SYM_END)
{
getsym();
}
else
{
error(17); // ';' or 'end' expected.
}
}
else if (sym == SYM_WHILE)
{ // while statement
cx1 = cx;
getsym();
set1 = createset(SYM_DO, SYM_NULL);
set = uniteset(set1, fsys);
condition(set);
destroyset(set1);
destroyset(set);
cx2 = cx;
gen(JPC, 0, 0);
if (sym == SYM_DO)
{
getsym();
}
else
{
error(18); // 'do' expected.
}
statement(fsys);
gen(JMP, 0, cx1);
code[cx2].a = cx;
}
else //added by yzhang 02-02-28
test(fsys, phi, 19);
} // statement
//////////////////////////////////////////////////////////////////////
void block(symset fsys)
{
int cx0; // initial code index
mask* mk;
int block_dx;
int savedTx;
symset set1, set;
dx = 3;
block_dx = dx;
mk = (mask*) &table[tx];
mk->address = cx;
gen(JMP, 0, 0);
if (level > MAXLEVEL)
{
error(32); // There are too many levels.
}
do
{
if (sym == SYM_CONST)
{ // constant declarations
getsym();
do
{
constdeclaration();
while (sym == SYM_COMMA)
{
getsym();
constdeclaration();
}
if (sym == SYM_SEMICOLON)
{
getsym();
}
else
{
error(5); // Missing ',' or ';'.
}
}
while (sym == SYM_IDENTIFIER);
} // if
if (sym == SYM_VAR)
{ // variable declarations
getsym();
do
{
vardeclaration();
while (sym == SYM_COMMA)
{
getsym();
vardeclaration();
}
if (sym == SYM_SEMICOLON)
{
getsym();
}
else
{
error(5); // Missing ',' or ';'.
}
}
while (sym == SYM_IDENTIFIER);
block_dx = dx; // modified by yzhang 02-03-15
} // if
while (sym == SYM_PROCEDURE)
{ // procere declarations
getsym();
if (sym == SYM_IDENTIFIER)
{
enter(ID_PROCEDURE);
getsym();
}
else
{
error(4); // There must be an identifier to follow 'const', 'var', or 'procere'.
}
if (sym == SYM_SEMICOLON)
{
getsym();
}
else
{
error(5); // Missing ',' or ';'.
}
level++;
savedTx = tx;
set1 = createset(SYM_SEMICOLON, SYM_NULL);
set = uniteset(set1, fsys);
block(set);
destroyset(set1);
destroyset(set);
tx = savedTx;
level--;
if (sym == SYM_SEMICOLON)
{
getsym();
set1 = createset(SYM_IDENTIFIER, SYM_PROCEDURE, SYM_NULL);
set = uniteset(statbegsys, set1);
test(set, fsys, 6);
destroyset(set1);
destroyset(set);
}
else
{
error(5); // Missing ',' or ';'.
}
} // while
set1 = createset(SYM_IDENTIFIER, SYM_NULL);
set = uniteset(statbegsys, set1);
test(set, declbegsys, 7);
destroyset(set1);
destroyset(set);
}
while (inset(sym, declbegsys));
code[mk->address].a = cx;
mk->address = cx;
cx0 = cx;
gen(INT, 0, block_dx);
set1 = createset(SYM_SEMICOLON, SYM_END, SYM_NULL);
set = uniteset(set1, fsys);
statement(set);
destroyset(set1);
destroyset(set);
gen(OPR, 0, OPR_RET); // return
test(fsys, phi, 8); // test for error: Follow the statement is an incorrect symbol.
listcode(cx0, cx);
} // block
//////////////////////////////////////////////////////////////////////
int base(int stack[], int currentLevel, int levelDiff)
{
int b = currentLevel;
while (levelDiff--)
b = stack[b];
return b;
} // base
//////////////////////////////////////////////////////////////////////
// interprets and executes codes.
void interpret()
{
int pc; // program counter
int stack[STACKSIZE];
int top; // top of stack
int b; // program, base, and top-stack register
instruction i; // instruction register
printf("Begin executing PL/0 program.\n");
fprintf(outfile, "Begin executing PL/0 program.\n");
pc = 0;
b = 1;
top = 3;
stack[1] = stack[2] = stack[3] = 0;
do
{
i = code[pc++];
switch (i.f)
{
case LIT:
stack[++top] = i.a;
break;
case OPR:
switch (i.a) // operator
{
case OPR_RET:
top = b - 1;
pc = stack[top + 3];
b = stack[top + 2];
break;
case OPR_NEG:
stack[top] = -stack[top];
break;
case OPR_ADD:
top--;
stack[top] += stack[top + 1];
break;
case OPR_MIN:
top--;
stack[top] -= stack[top + 1];
break;
case OPR_MUL:
top--;
stack[top] *= stack[top + 1];
break;
case OPR_DIV:
top--;
if (stack[top + 1] == 0)
{
fprintf(stderr, "Runtime Error: Divided by zero.\n");
fprintf(stderr, "Program terminated.\n");
continue;
}
stack[top] /= stack[top + 1];
break;
case OPR_ODD:
stack[top] %= 2;
break;
case OPR_EQU:
top--;
stack[top] = stack[top] == stack[top + 1];
break;
case OPR_NEQ:
top--;
stack[top] = stack[top] != stack[top + 1];
case OPR_LES:
top--;
stack[top] = stack[top] < stack[top + 1];
break;
case OPR_GEQ:
top--;
stack[top] = stack[top] >= stack[top + 1];
case OPR_GTR:
top--;
stack[top] = stack[top] > stack[top + 1];
break;
case OPR_LEQ:
top--;
stack[top] = stack[top] <= stack[top + 1];
} // switch
break;
case LOD:
stack[++top] = stack[base(stack, b, i.l) + i.a];
break;
case STO:
stack[base(stack, b, i.l) + i.a] = stack[top];
//printf("%d\n", stack[top]);
fprintf(outfile, "%d\n", stack[top]);
top--;
break;
case CAL:
stack[top + 1] = base(stack, b, i.l);
// generate new block mark
stack[top + 2] = b;
stack[top + 3] = pc;
b = top + 1;
pc = i.a;
break;
case INT:
top += i.a;
break;
case JMP:
pc = i.a;
break;
case JPC:
if (stack[top] == 0)
pc = i.a;
top--;
break;
} // switch
}
while (pc);
//printf("End executing PL/0 program.\n");
fprintf(outfile, "End executing PL/0 program.\n");
} // interpret
//////////////////////////////////////////////////////////////////////
void main ()
{
FILE* hbin;
char s[80],*finddot;
int i;
symset set, set1, set2;
printf("Please input source file name: "); // get file name to be compiled
scanf("%s", s);
if ((infile = fopen(s, "r")) == NULL)
{
printf("File %s can't be opened.\n", s);
exit(1);
}
#if 1 // added by yzhang 02-02-28
// open the output file
finddot = strchr(s,'.');
if (finddot!=NULL){
strcpy(finddot, ".out");
}else{
strcat(s, ".out");
printf("%s\n", s);
}
printf("Output File is %s\n", s);
if ((outfile = fopen(s, "w")) == NULL)
{
printf("File %s can't be opened.\n", s);
exit(1);
}
#endif
phi = createset(SYM_NULL);
relset = createset(SYM_EQU, SYM_NEQ, SYM_LES, SYM_LEQ, SYM_GTR, SYM_GEQ, SYM_NULL);
// create begin symbol sets
declbegsys = createset(SYM_CONST, SYM_VAR, SYM_PROCEDURE, SYM_NULL);
statbegsys = createset(SYM_BEGIN, SYM_CALL, SYM_IF, SYM_WHILE, SYM_NULL);
facbegsys = createset(SYM_IDENTIFIER, SYM_NUMBER, SYM_LPAREN, SYM_NULL);
err = cc = cx = ll = 0; // initialize global variables
ch = ' ';
kk = MAXIDLEN;
getsym();
set1 = createset(SYM_PERIOD, SYM_NULL);
set2 = uniteset(declbegsys, statbegsys);
set = uniteset(set1, set2);
block(set);
destroyset(set1);
destroyset(set2);
destroyset(set);
destroyset(phi);
destroyset(relset);
destroyset(declbegsys);
destroyset(statbegsys);
destroyset(facbegsys);
if (sym != SYM_PERIOD)
error(9); // '.' expected.
if (err == 0)
{
hbin = fopen("hbin.txt", "w");
for (i = 0; i < cx; i++)
fwrite(&code[i], sizeof(instruction), 1, hbin);
fclose(hbin);
}
if (err == 0)
interpret();
else
printf("There are %d error(s) in PL/0 program.\n", err);
listcode(0, cx);
// close all files, added by yzhang, 02-02-28
fclose(infile);
fclose(outfile);
} // main
//////////////////////////////////////////////////////////////////////
// eof pl0.c
⑥ 編譯程序安裝在計算機的哪裡
舉例來說:
當你使用C編寫代碼,使用編譯器編譯後,即生成了可執行程序。當可執行程序被操作系統的載入器載入到內存、並准備好必要的數據後從代碼段開始執行,這時的代碼段代碼已經是機器碼了,無須編譯。當然,可執行程序里的所有數據並非都是代碼,有些是寫給操作系統看的,以使操作系統能為程序的執行做好必要准備。
至於說DOS命令,分為外部命令和內部命令。外部命令和一般的可執行程序沒有區別,他以可執行程序文件的形式存在。沒有這個文件就不能運行這個命令;內部命令是固化在操作系統中的代碼模塊,一般以DLL文件的形式存在。至於哪個DLL文件包含特定的內部命令的代碼,就必須查資料了。
CPU所支持的指令集,是由CPU的物理設計決定的,並不是說有什麼指令存放在CPU上。
當然,如果是解釋性的語言。那麼,可執行程序是一邊被解釋(編譯)一邊被執行的。所以他的速度要慢些。並且必須安裝對應的編譯(解釋)程序。比如JAVA。
⑦ 編譯程序和解釋程序具體在哪具體是哪個文件
說是編譯程序和解釋程序,但是並不是具體的某個文件,它們是固化了的東西。
⑧ 如何將經過編譯後的程序得到它的源程序
不太可能,因為編譯後的程序是機器語言,最多還原成匯編語言,不可能還原成高級語言的源程序。
就好像香腸不可能還原成豬,最多隻能還原成肉末一樣。
⑨ 怎麼查看文件的源程序
打開瀏覽器→查看→源文件
找FLASH源文件會比較麻煩因為一些FLASH都把源文件隱藏
可以這樣找
打開瀏覽器→查看→源文件→編輯→查找下一個
輸入flash查找到前面是http開頭以jtp結尾就是了
⑩ 請問visualc++6.0編譯生成的源程序文件在哪兒
源程序文件 要不就是沒有,要不就是a那個文件,就是標注c_file那個。
生成的可執行程序在debug這個文件夾下邊。